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);
458 static void warn_if_field_exists(lua_State *L, int table,
459 const char *fieldname, const std::string &message)
461 lua_getfield(L, table, fieldname);
462 if(!lua_isnil(L, -1)){
463 infostream<<script_get_backtrace(L)<<std::endl;
464 infostream<<"WARNING: field \""<<fieldname<<"\": "
465 <<message<<std::endl;
474 static void inventory_set_list_from_lua(Inventory *inv, const char *name,
475 lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1)
478 tableindex = lua_gettop(L) + 1 + tableindex;
479 // If nil, delete list
480 if(lua_isnil(L, tableindex)){
481 inv->deleteList(name);
484 // Otherwise set list
485 std::list<std::string> items;
486 luaL_checktype(L, tableindex, LUA_TTABLE);
487 int table = tableindex;
489 while(lua_next(L, table) != 0){
490 // key at index -2 and value at index -1
491 luaL_checktype(L, -1, LUA_TSTRING);
492 std::string itemstring = lua_tostring(L, -1);
493 items.push_back(itemstring);
494 // removes value, keeps key for next iteration
497 int listsize = (forcesize != -1) ? forcesize : items.size();
498 InventoryList *invlist = inv->addList(name, listsize);
500 for(std::list<std::string>::const_iterator
501 i = items.begin(); i != items.end(); i++){
502 if(forcesize != -1 && index == forcesize)
504 const std::string &itemstring = *i;
505 InventoryItem *newitem = NULL;
507 newitem = InventoryItem::deSerialize(itemstring,
509 InventoryItem *olditem = invlist->changeItem(index, newitem);
513 while(forcesize != -1 && index < forcesize){
514 InventoryItem *olditem = invlist->changeItem(index, NULL);
520 static void inventory_get_list_to_lua(Inventory *inv, const char *name,
523 InventoryList *invlist = inv->getList(name);
528 // Get the table insert function
529 lua_getglobal(L, "table");
530 lua_getfield(L, -1, "insert");
531 int table_insert = lua_gettop(L);
532 // Create and fill table
534 int table = lua_gettop(L);
535 for(u32 i=0; i<invlist->getSize(); i++){
536 InventoryItem *item = invlist->getItem(i);
537 lua_pushvalue(L, table_insert);
538 lua_pushvalue(L, table);
540 lua_pushstring(L, "");
542 lua_pushstring(L, item->getItemString().c_str());
544 if(lua_pcall(L, 2, 0, 0))
545 script_error(L, "error: %s", lua_tostring(L, -1));
550 ToolDiggingProperties
553 static ToolDiggingProperties read_tool_digging_properties(
554 lua_State *L, int table)
556 ToolDiggingProperties prop;
557 getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
558 getfloatfield(L, table, "basetime", prop.basetime);
559 getfloatfield(L, table, "dt_weight", prop.dt_weight);
560 getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
561 getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
562 getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
563 getfloatfield(L, table, "basedurability", prop.basedurability);
564 getfloatfield(L, table, "dd_weight", prop.dd_weight);
565 getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
566 getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
567 getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
571 static void set_tool_digging_properties(lua_State *L, int table,
572 const ToolDiggingProperties &prop)
574 setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
575 setfloatfield(L, table, "basetime", prop.basetime);
576 setfloatfield(L, table, "dt_weight", prop.dt_weight);
577 setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
578 setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
579 setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
580 setfloatfield(L, table, "basedurability", prop.basedurability);
581 setfloatfield(L, table, "dd_weight", prop.dd_weight);
582 setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
583 setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
584 setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
587 static void push_tool_digging_properties(lua_State *L,
588 const ToolDiggingProperties &prop)
591 set_tool_digging_properties(L, -1, prop);
598 static ToolDefinition read_tool_definition(lua_State *L, int table)
601 getstringfield(L, table, "image", def.imagename);
602 def.properties = read_tool_digging_properties(L, table);
606 static void push_tool_definition(lua_State *L, const ToolDefinition &def)
609 lua_pushstring(L, def.imagename.c_str());
610 lua_setfield(L, -2, "image");
611 set_tool_digging_properties(L, -1, def.properties);
615 EnumString definitions
618 struct EnumString es_DrawType[] =
620 {NDT_NORMAL, "normal"},
621 {NDT_AIRLIKE, "airlike"},
622 {NDT_LIQUID, "liquid"},
623 {NDT_FLOWINGLIQUID, "flowingliquid"},
624 {NDT_GLASSLIKE, "glasslike"},
625 {NDT_ALLFACES, "allfaces"},
626 {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
627 {NDT_TORCHLIKE, "torchlike"},
628 {NDT_SIGNLIKE, "signlike"},
629 {NDT_PLANTLIKE, "plantlike"},
630 {NDT_FENCELIKE, "fencelike"},
631 {NDT_RAILLIKE, "raillike"},
635 struct EnumString es_ContentParamType[] =
638 {CPT_LIGHT, "light"},
639 {CPT_MINERAL, "mineral"},
640 {CPT_FACEDIR_SIMPLE, "facedir_simple"},
644 struct EnumString es_LiquidType[] =
646 {LIQUID_NONE, "none"},
647 {LIQUID_FLOWING, "flowing"},
648 {LIQUID_SOURCE, "source"},
652 struct EnumString es_NodeBoxType[] =
654 {NODEBOX_REGULAR, "regular"},
655 {NODEBOX_FIXED, "fixed"},
656 {NODEBOX_WALLMOUNTED, "wallmounted"},
660 struct EnumString es_Diggability[] =
662 {DIGGABLE_NOT, "not"},
663 {DIGGABLE_NORMAL, "normal"},
664 {DIGGABLE_CONSTANT, "constant"},
672 static int l_register_nodedef_defaults(lua_State *L)
674 luaL_checktype(L, 1, LUA_TTABLE);
676 lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
677 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
682 // Register new object prototype
683 // register_entity(name, prototype)
684 static int l_register_entity(lua_State *L)
686 std::string name = luaL_checkstring(L, 1);
687 check_modname_prefix(L, name);
688 //infostream<<"register_entity: "<<name<<std::endl;
689 luaL_checktype(L, 2, LUA_TTABLE);
691 // Get minetest.registered_entities
692 lua_getglobal(L, "minetest");
693 lua_getfield(L, -1, "registered_entities");
694 luaL_checktype(L, -1, LUA_TTABLE);
695 int registered_entities = lua_gettop(L);
696 lua_pushvalue(L, 2); // Object = param 2 -> stack top
697 // registered_entities[name] = object
698 lua_setfield(L, registered_entities, name.c_str());
700 // Get registered object to top of stack
703 // Set __index to point to itself
704 lua_pushvalue(L, -1);
705 lua_setfield(L, -2, "__index");
707 // Set metatable.__index = metatable
708 luaL_getmetatable(L, "minetest.entity");
709 lua_pushvalue(L, -1); // duplicate metatable
710 lua_setfield(L, -2, "__index");
711 // Set object metatable
712 lua_setmetatable(L, -2);
714 return 0; /* number of results */
717 class LuaABM : public ActiveBlockModifier
723 std::set<std::string> m_trigger_contents;
724 std::set<std::string> m_required_neighbors;
725 float m_trigger_interval;
726 u32 m_trigger_chance;
728 LuaABM(lua_State *L, int id,
729 const std::set<std::string> &trigger_contents,
730 const std::set<std::string> &required_neighbors,
731 float trigger_interval, u32 trigger_chance):
734 m_trigger_contents(trigger_contents),
735 m_required_neighbors(required_neighbors),
736 m_trigger_interval(trigger_interval),
737 m_trigger_chance(trigger_chance)
740 virtual std::set<std::string> getTriggerContents()
742 return m_trigger_contents;
744 virtual std::set<std::string> getRequiredNeighbors()
746 return m_required_neighbors;
748 virtual float getTriggerInterval()
750 return m_trigger_interval;
752 virtual u32 getTriggerChance()
754 return m_trigger_chance;
756 virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
757 u32 active_object_count, u32 active_object_count_wider)
759 lua_State *L = m_lua;
762 assert(lua_checkstack(L, 20));
763 StackUnroller stack_unroller(L);
765 // Get minetest.registered_abms
766 lua_getglobal(L, "minetest");
767 lua_getfield(L, -1, "registered_abms");
768 luaL_checktype(L, -1, LUA_TTABLE);
769 int registered_abms = lua_gettop(L);
771 // Get minetest.registered_abms[m_id]
772 lua_pushnumber(L, m_id);
773 lua_gettable(L, registered_abms);
778 luaL_checktype(L, -1, LUA_TTABLE);
779 lua_getfield(L, -1, "action");
780 luaL_checktype(L, -1, LUA_TFUNCTION);
782 pushnode(L, n, env->getGameDef()->ndef());
783 lua_pushnumber(L, active_object_count);
784 lua_pushnumber(L, active_object_count_wider);
785 if(lua_pcall(L, 4, 0, 0))
786 script_error(L, "error: %s", lua_tostring(L, -1));
790 // register_abm({...})
791 static int l_register_abm(lua_State *L)
793 //infostream<<"register_abm"<<std::endl;
794 luaL_checktype(L, 1, LUA_TTABLE);
796 // Get minetest.registered_abms
797 lua_getglobal(L, "minetest");
798 lua_getfield(L, -1, "registered_abms");
799 luaL_checktype(L, -1, LUA_TTABLE);
800 int registered_abms = lua_gettop(L);
805 lua_pushnumber(L, id);
806 lua_gettable(L, registered_abms);
814 infostream<<"register_abm: id="<<id<<std::endl;
816 // registered_abms[id] = spec
817 lua_pushnumber(L, id);
819 lua_settable(L, registered_abms);
821 return 0; /* number of results */
824 // register_tool(name, {lots of stuff})
825 static int l_register_tool(lua_State *L)
827 std::string name = luaL_checkstring(L, 1);
828 check_modname_prefix(L, name);
829 //infostream<<"register_tool: "<<name<<std::endl;
830 luaL_checktype(L, 2, LUA_TTABLE);
833 // Get server from registry
834 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
835 Server *server = (Server*)lua_touserdata(L, -1);
836 // And get the writable tool definition manager from the server
837 IWritableToolDefManager *tooldef =
838 server->getWritableToolDefManager();
840 ToolDefinition def = read_tool_definition(L, table);
842 tooldef->registerTool(name, def);
843 return 0; /* number of results */
846 // register_craftitem(name, {lots of stuff})
847 static int l_register_craftitem(lua_State *L)
849 std::string name = luaL_checkstring(L, 1);
850 check_modname_prefix(L, name);
851 //infostream<<"register_craftitem: "<<name<<std::endl;
852 luaL_checktype(L, 2, LUA_TTABLE);
855 // Get server from registry
856 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
857 Server *server = (Server*)lua_touserdata(L, -1);
858 // And get the writable CraftItem definition manager from the server
859 IWritableCraftItemDefManager *craftitemdef =
860 server->getWritableCraftItemDefManager();
862 // Check if on_drop is defined
863 lua_getfield(L, table, "on_drop");
864 bool got_on_drop = !lua_isnil(L, -1);
867 // Check if on_use is defined
868 lua_getfield(L, table, "on_use");
869 bool got_on_use = !lua_isnil(L, -1);
872 CraftItemDefinition def;
874 getstringfield(L, table, "image", def.imagename);
875 getstringfield(L, table, "cookresult_itemstring", def.cookresult_item);
876 getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
877 getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
878 def.usable = getboolfield_default(L, table, "usable", got_on_use);
879 getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
880 def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
881 def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
883 // If an on_drop callback is defined, force dropcount to 1
888 craftitemdef->registerCraftItem(name, def);
890 lua_pushvalue(L, table);
891 scriptapi_add_craftitem(L, name.c_str());
893 return 0; /* number of results */
896 // register_node(name, {lots of stuff})
897 static int l_register_node(lua_State *L)
899 std::string name = luaL_checkstring(L, 1);
900 check_modname_prefix(L, name);
901 //infostream<<"register_node: "<<name<<std::endl;
902 luaL_checktype(L, 2, LUA_TTABLE);
903 int nodedef_table = 2;
905 // Get server from registry
906 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
907 Server *server = (Server*)lua_touserdata(L, -1);
908 // And get the writable node definition manager from the server
909 IWritableNodeDefManager *nodedef =
910 server->getWritableNodeDefManager();
912 // Get default node definition from registry
913 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
914 int nodedef_default = lua_gettop(L);
917 Add to minetest.registered_nodes with default as metatable
920 // Get the node definition table given as parameter
921 lua_pushvalue(L, nodedef_table);
923 // Set __index to point to itself
924 lua_pushvalue(L, -1);
925 lua_setfield(L, -2, "__index");
927 // Set nodedef_default as metatable for the definition
928 lua_pushvalue(L, nodedef_default);
929 lua_setmetatable(L, nodedef_table);
931 // minetest.registered_nodes[name] = nodedef
932 lua_getglobal(L, "minetest");
933 lua_getfield(L, -1, "registered_nodes");
934 luaL_checktype(L, -1, LUA_TTABLE);
935 lua_pushstring(L, name.c_str());
936 lua_pushvalue(L, nodedef_table);
945 // Default to getting the corresponding NodeItem when dug
946 f.dug_item = std::string("NodeItem \"")+name+"\" 1";
948 // Default to unknown_block.png as all textures
949 f.setAllTextures("unknown_block.png");
952 Read definiton from Lua
957 /* Visual definition */
959 f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
961 getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
963 lua_getfield(L, nodedef_table, "tile_images");
964 if(lua_istable(L, -1)){
965 int table = lua_gettop(L);
968 while(lua_next(L, table) != 0){
969 // key at index -2 and value at index -1
970 if(lua_isstring(L, -1))
971 f.tname_tiles[i] = lua_tostring(L, -1);
973 f.tname_tiles[i] = "";
974 // removes value, keeps key for next iteration
982 // Copy last value to all remaining textures
984 std::string lastname = f.tname_tiles[i-1];
986 f.tname_tiles[i] = lastname;
993 getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
995 lua_getfield(L, nodedef_table, "special_materials");
996 if(lua_istable(L, -1)){
997 int table = lua_gettop(L);
1000 while(lua_next(L, table) != 0){
1001 // key at index -2 and value at index -1
1002 int smtable = lua_gettop(L);
1003 std::string tname = getstringfield_default(
1004 L, smtable, "image", "");
1005 bool backface_culling = getboolfield_default(
1006 L, smtable, "backface_culling", true);
1007 MaterialSpec mspec(tname, backface_culling);
1008 f.setSpecialMaterial(i, mspec);
1009 // removes value, keeps key for next iteration
1020 f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
1024 lua_getfield(L, nodedef_table, "post_effect_color");
1025 if(!lua_isnil(L, -1))
1026 f.post_effect_color = readARGB8(L, -1);
1029 f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
1030 es_ContentParamType, CPT_NONE);
1032 // True for all ground-like things like stone and mud, false for eg. trees
1033 getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
1034 f.light_propagates = (f.param_type == CPT_LIGHT);
1035 warn_if_field_exists(L, nodedef_table, "light_propagates",
1036 "deprecated: determined from paramtype");
1037 getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
1038 // This is used for collision detection.
1039 // Also for general solidness queries.
1040 getboolfield(L, nodedef_table, "walkable", f.walkable);
1041 // Player can point to these
1042 getboolfield(L, nodedef_table, "pointable", f.pointable);
1043 // Player can dig these
1044 getboolfield(L, nodedef_table, "diggable", f.diggable);
1045 // Player can climb these
1046 getboolfield(L, nodedef_table, "climbable", f.climbable);
1047 // Player can build on these
1048 getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
1049 // If true, param2 is set to direction when placed. Used for torches.
1050 // NOTE: the direction format is quite inefficient and should be changed
1051 getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
1052 // Whether this content type often contains mineral.
1053 // Used for texture atlas creation.
1054 // Currently only enabled for CONTENT_STONE.
1055 getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
1056 // Inventory item string as which the node appears in inventory when dug.
1057 // Mineral overrides this.
1058 getstringfield(L, nodedef_table, "dug_item", f.dug_item);
1059 // Extra dug item and its rarity
1060 getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
1061 // Usual get interval for extra dug item
1062 getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
1063 // Metadata name of node (eg. "furnace")
1064 getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
1065 // Whether the node is non-liquid, source liquid or flowing liquid
1066 f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
1067 es_LiquidType, LIQUID_NONE);
1068 // If the content is liquid, this is the flowing version of the liquid.
1069 getstringfield(L, nodedef_table, "liquid_alternative_flowing",
1070 f.liquid_alternative_flowing);
1071 // If the content is liquid, this is the source version of the liquid.
1072 getstringfield(L, nodedef_table, "liquid_alternative_source",
1073 f.liquid_alternative_source);
1074 // Viscosity for fluid flow, ranging from 1 to 7, with
1075 // 1 giving almost instantaneous propagation and 7 being
1076 // the slowest possible
1077 f.liquid_viscosity = getintfield_default(L, nodedef_table,
1078 "liquid_viscosity", f.liquid_viscosity);
1079 // Amount of light the node emits
1080 f.light_source = getintfield_default(L, nodedef_table,
1081 "light_source", f.light_source);
1082 f.damage_per_second = getintfield_default(L, nodedef_table,
1083 "damage_per_second", f.damage_per_second);
1085 lua_getfield(L, nodedef_table, "selection_box");
1086 if(lua_istable(L, -1)){
1087 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
1088 es_NodeBoxType, NODEBOX_REGULAR);
1090 lua_getfield(L, -1, "fixed");
1091 if(lua_istable(L, -1))
1092 f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
1095 lua_getfield(L, -1, "wall_top");
1096 if(lua_istable(L, -1))
1097 f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
1100 lua_getfield(L, -1, "wall_bottom");
1101 if(lua_istable(L, -1))
1102 f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
1105 lua_getfield(L, -1, "wall_side");
1106 if(lua_istable(L, -1))
1107 f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
1112 lua_getfield(L, nodedef_table, "material");
1113 if(lua_istable(L, -1)){
1114 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
1115 es_Diggability, DIGGABLE_NORMAL);
1117 getfloatfield(L, -1, "constant_time", f.material.constant_time);
1118 getfloatfield(L, -1, "weight", f.material.weight);
1119 getfloatfield(L, -1, "crackiness", f.material.crackiness);
1120 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
1121 getfloatfield(L, -1, "cuttability", f.material.cuttability);
1122 getfloatfield(L, -1, "flammability", f.material.flammability);
1126 getstringfield(L, nodedef_table, "cookresult_itemstring", f.cookresult_item);
1127 getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
1128 getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
1134 nodedef->set(name, f);
1136 return 0; /* number of results */
1139 // alias_node(name, convert_to_name)
1140 static int l_alias_node(lua_State *L)
1142 std::string name = luaL_checkstring(L, 1);
1143 std::string convert_to = luaL_checkstring(L, 2);
1145 // Get server from registry
1146 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1147 Server *server = (Server*)lua_touserdata(L, -1);
1148 // And get the writable node definition manager from the server
1149 IWritableNodeDefManager *nodedef =
1150 server->getWritableNodeDefManager();
1152 nodedef->setAlias(name, convert_to);
1154 return 0; /* number of results */
1157 // alias_tool(name, convert_to_name)
1158 static int l_alias_tool(lua_State *L)
1160 std::string name = luaL_checkstring(L, 1);
1161 std::string convert_to = luaL_checkstring(L, 2);
1163 // Get server from registry
1164 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1165 Server *server = (Server*)lua_touserdata(L, -1);
1166 // And get the writable tool definition manager from the server
1167 IWritableToolDefManager *tooldef =
1168 server->getWritableToolDefManager();
1170 tooldef->setAlias(name, convert_to);
1172 return 0; /* number of results */
1175 // alias_craftitem(name, convert_to_name)
1176 static int l_alias_craftitem(lua_State *L)
1178 std::string name = luaL_checkstring(L, 1);
1179 std::string convert_to = luaL_checkstring(L, 2);
1181 // Get server from registry
1182 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1183 Server *server = (Server*)lua_touserdata(L, -1);
1184 // And get the writable CraftItem definition manager from the server
1185 IWritableCraftItemDefManager *craftitemdef =
1186 server->getWritableCraftItemDefManager();
1188 craftitemdef->setAlias(name, convert_to);
1190 return 0; /* number of results */
1193 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
1194 static int l_register_craft(lua_State *L)
1196 //infostream<<"register_craft"<<std::endl;
1197 luaL_checktype(L, 1, LUA_TTABLE);
1200 // Get server from registry
1201 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1202 Server *server = (Server*)lua_touserdata(L, -1);
1203 // And get the writable craft definition manager from the server
1204 IWritableCraftDefManager *craftdef =
1205 server->getWritableCraftDefManager();
1209 std::vector<std::string> input;
1211 lua_getfield(L, table0, "output");
1212 luaL_checktype(L, -1, LUA_TSTRING);
1213 if(lua_isstring(L, -1))
1214 output = lua_tostring(L, -1);
1217 lua_getfield(L, table0, "recipe");
1218 luaL_checktype(L, -1, LUA_TTABLE);
1219 if(lua_istable(L, -1)){
1220 int table1 = lua_gettop(L);
1223 while(lua_next(L, table1) != 0){
1225 // key at index -2 and value at index -1
1226 luaL_checktype(L, -1, LUA_TTABLE);
1227 if(lua_istable(L, -1)){
1228 int table2 = lua_gettop(L);
1230 while(lua_next(L, table2) != 0){
1231 // key at index -2 and value at index -1
1232 luaL_checktype(L, -1, LUA_TSTRING);
1233 input.push_back(lua_tostring(L, -1));
1234 // removes value, keeps key for next iteration
1242 if(colcount != width){
1244 error += "Invalid crafting recipe (output=\""
1246 throw LuaError(L, error);
1249 // removes value, keeps key for next iteration
1256 CraftDefinition def(output, width, input);
1257 craftdef->registerCraft(def);
1259 return 0; /* number of results */
1262 // setting_get(name)
1263 static int l_setting_get(lua_State *L)
1265 const char *name = luaL_checkstring(L, 1);
1267 std::string value = g_settings->get(name);
1268 lua_pushstring(L, value.c_str());
1269 } catch(SettingNotFoundException &e){
1275 // setting_getbool(name)
1276 static int l_setting_getbool(lua_State *L)
1278 const char *name = luaL_checkstring(L, 1);
1280 bool value = g_settings->getBool(name);
1281 lua_pushboolean(L, value);
1282 } catch(SettingNotFoundException &e){
1288 // chat_send_all(text)
1289 static int l_chat_send_all(lua_State *L)
1291 const char *text = luaL_checkstring(L, 1);
1292 // Get server from registry
1293 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1294 Server *server = (Server*)lua_touserdata(L, -1);
1296 server->notifyPlayers(narrow_to_wide(text));
1300 // chat_send_player(name, text)
1301 static int l_chat_send_player(lua_State *L)
1303 const char *name = luaL_checkstring(L, 1);
1304 const char *text = luaL_checkstring(L, 2);
1305 // Get server from registry
1306 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1307 Server *server = (Server*)lua_touserdata(L, -1);
1309 server->notifyPlayer(name, narrow_to_wide(text));
1313 // get_player_privs(name, text)
1314 static int l_get_player_privs(lua_State *L)
1316 const char *name = luaL_checkstring(L, 1);
1317 // Get server from registry
1318 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1319 Server *server = (Server*)lua_touserdata(L, -1);
1322 int table = lua_gettop(L);
1323 u64 privs_i = server->getPlayerAuthPrivs(name);
1324 // Special case for the "name" setting (local player / server owner)
1325 if(name == g_settings->get("name"))
1327 std::set<std::string> privs_s = privsToSet(privs_i);
1328 for(std::set<std::string>::const_iterator
1329 i = privs_s.begin(); i != privs_s.end(); i++){
1330 lua_pushboolean(L, true);
1331 lua_setfield(L, table, i->c_str());
1333 lua_pushvalue(L, table);
1337 static const struct luaL_Reg minetest_f [] = {
1338 {"register_nodedef_defaults", l_register_nodedef_defaults},
1339 {"register_entity", l_register_entity},
1340 {"register_tool", l_register_tool},
1341 {"register_craftitem", l_register_craftitem},
1342 {"register_node", l_register_node},
1343 {"register_craft", l_register_craft},
1344 {"register_abm", l_register_abm},
1345 {"alias_node", l_alias_node},
1346 {"alias_tool", l_alias_tool},
1347 {"alias_craftitem", l_alias_craftitem},
1348 {"setting_get", l_setting_get},
1349 {"setting_getbool", l_setting_getbool},
1350 {"chat_send_all", l_chat_send_all},
1351 {"chat_send_player", l_chat_send_player},
1352 {"get_player_privs", l_get_player_privs},
1360 static const struct luaL_Reg minetest_entity_m [] = {
1365 Getters for stuff in main tables
1368 static void objectref_get(lua_State *L, u16 id)
1370 // Get minetest.object_refs[i]
1371 lua_getglobal(L, "minetest");
1372 lua_getfield(L, -1, "object_refs");
1373 luaL_checktype(L, -1, LUA_TTABLE);
1374 lua_pushnumber(L, id);
1375 lua_gettable(L, -2);
1376 lua_remove(L, -2); // object_refs
1377 lua_remove(L, -2); // minetest
1380 static void luaentity_get(lua_State *L, u16 id)
1382 // Get minetest.luaentities[i]
1383 lua_getglobal(L, "minetest");
1384 lua_getfield(L, -1, "luaentities");
1385 luaL_checktype(L, -1, LUA_TTABLE);
1386 lua_pushnumber(L, id);
1387 lua_gettable(L, -2);
1388 lua_remove(L, -2); // luaentities
1389 lua_remove(L, -2); // minetest
1396 #define method(class, name) {#name, class::l_##name}
1406 ServerEnvironment *m_env;
1408 static const char className[];
1409 static const luaL_reg methods[];
1411 static NodeMetaRef *checkobject(lua_State *L, int narg)
1413 luaL_checktype(L, narg, LUA_TUSERDATA);
1414 void *ud = luaL_checkudata(L, narg, className);
1415 if(!ud) luaL_typerror(L, narg, className);
1416 return *(NodeMetaRef**)ud; // unbox pointer
1419 static NodeMetadata* getmeta(NodeMetaRef *ref)
1421 NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
1425 /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
1427 NodeMetadata *meta = getmeta(ref);
1430 if(meta->typeId() != NODEMETA_GENERIC)
1432 return (IGenericNodeMetadata*)meta;
1435 static void reportMetadataChange(NodeMetaRef *ref)
1437 // Inform other things that the metadata has changed
1438 v3s16 blockpos = getNodeBlockPos(ref->m_p);
1440 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1442 ref->m_env->getMap().dispatchEvent(&event);
1443 // Set the block to be saved
1444 MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
1446 block->raiseModified(MOD_STATE_WRITE_NEEDED,
1447 "NodeMetaRef::reportMetadataChange");
1450 // Exported functions
1452 // garbage collector
1453 static int gc_object(lua_State *L) {
1454 NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
1460 static int l_get_type(lua_State *L)
1462 NodeMetaRef *ref = checkobject(L, 1);
1463 NodeMetadata *meta = getmeta(ref);
1469 lua_pushstring(L, meta->typeName());
1473 // allows_text_input(self)
1474 static int l_allows_text_input(lua_State *L)
1476 NodeMetaRef *ref = checkobject(L, 1);
1477 NodeMetadata *meta = getmeta(ref);
1478 if(meta == NULL) return 0;
1480 lua_pushboolean(L, meta->allowsTextInput());
1484 // set_text(self, text)
1485 static int l_set_text(lua_State *L)
1487 NodeMetaRef *ref = checkobject(L, 1);
1488 NodeMetadata *meta = getmeta(ref);
1489 if(meta == NULL) return 0;
1491 std::string text = lua_tostring(L, 2);
1492 meta->setText(text);
1493 reportMetadataChange(ref);
1498 static int l_get_text(lua_State *L)
1500 NodeMetaRef *ref = checkobject(L, 1);
1501 NodeMetadata *meta = getmeta(ref);
1502 if(meta == NULL) return 0;
1504 std::string text = meta->getText();
1505 lua_pushstring(L, text.c_str());
1510 static int l_get_owner(lua_State *L)
1512 NodeMetaRef *ref = checkobject(L, 1);
1513 NodeMetadata *meta = getmeta(ref);
1514 if(meta == NULL) return 0;
1516 std::string owner = meta->getOwner();
1517 lua_pushstring(L, owner.c_str());
1521 /* IGenericNodeMetadata interface */
1523 // set_infotext(self, text)
1524 static int l_set_infotext(lua_State *L)
1526 infostream<<__FUNCTION_NAME<<std::endl;
1527 NodeMetaRef *ref = checkobject(L, 1);
1528 NodeMetadata *meta = getmeta(ref);
1529 if(meta == NULL) return 0;
1531 std::string text = lua_tostring(L, 2);
1532 meta->setInfoText(text);
1533 reportMetadataChange(ref);
1537 // inventory_set_list(self, name, {item1, item2, ...})
1538 static int l_inventory_set_list(lua_State *L)
1540 NodeMetaRef *ref = checkobject(L, 1);
1541 NodeMetadata *meta = getmeta(ref);
1542 if(meta == NULL) return 0;
1544 Inventory *inv = meta->getInventory();
1545 const char *name = lua_tostring(L, 2);
1546 inventory_set_list_from_lua(inv, name, L, 3,
1547 ref->m_env->getGameDef());
1548 reportMetadataChange(ref);
1552 // inventory_get_list(self, name)
1553 static int l_inventory_get_list(lua_State *L)
1555 NodeMetaRef *ref = checkobject(L, 1);
1556 NodeMetadata *meta = getmeta(ref);
1557 if(meta == NULL) return 0;
1559 Inventory *inv = meta->getInventory();
1560 const char *name = lua_tostring(L, 2);
1561 inventory_get_list_to_lua(inv, name, L);
1565 // set_inventory_draw_spec(self, text)
1566 static int l_set_inventory_draw_spec(lua_State *L)
1568 NodeMetaRef *ref = checkobject(L, 1);
1569 NodeMetadata *meta = getmeta(ref);
1570 if(meta == NULL) return 0;
1572 std::string text = lua_tostring(L, 2);
1573 meta->setInventoryDrawSpec(text);
1574 reportMetadataChange(ref);
1578 // set_allow_text_input(self, text)
1579 static int l_set_allow_text_input(lua_State *L)
1581 NodeMetaRef *ref = checkobject(L, 1);
1582 NodeMetadata *meta = getmeta(ref);
1583 if(meta == NULL) return 0;
1585 bool b = lua_toboolean(L, 2);
1586 meta->setAllowTextInput(b);
1587 reportMetadataChange(ref);
1591 // set_allow_removal(self, text)
1592 static int l_set_allow_removal(lua_State *L)
1594 NodeMetaRef *ref = checkobject(L, 1);
1595 NodeMetadata *meta = getmeta(ref);
1596 if(meta == NULL) return 0;
1598 bool b = lua_toboolean(L, 2);
1599 meta->setRemovalDisabled(!b);
1600 reportMetadataChange(ref);
1604 // set_enforce_owner(self, text)
1605 static int l_set_enforce_owner(lua_State *L)
1607 NodeMetaRef *ref = checkobject(L, 1);
1608 NodeMetadata *meta = getmeta(ref);
1609 if(meta == NULL) return 0;
1611 bool b = lua_toboolean(L, 2);
1612 meta->setEnforceOwner(b);
1613 reportMetadataChange(ref);
1617 // is_inventory_modified(self)
1618 static int l_is_inventory_modified(lua_State *L)
1620 NodeMetaRef *ref = checkobject(L, 1);
1621 NodeMetadata *meta = getmeta(ref);
1622 if(meta == NULL) return 0;
1624 lua_pushboolean(L, meta->isInventoryModified());
1628 // reset_inventory_modified(self)
1629 static int l_reset_inventory_modified(lua_State *L)
1631 NodeMetaRef *ref = checkobject(L, 1);
1632 NodeMetadata *meta = getmeta(ref);
1633 if(meta == NULL) return 0;
1635 meta->resetInventoryModified();
1636 reportMetadataChange(ref);
1640 // is_text_modified(self)
1641 static int l_is_text_modified(lua_State *L)
1643 NodeMetaRef *ref = checkobject(L, 1);
1644 NodeMetadata *meta = getmeta(ref);
1645 if(meta == NULL) return 0;
1647 lua_pushboolean(L, meta->isTextModified());
1651 // reset_text_modified(self)
1652 static int l_reset_text_modified(lua_State *L)
1654 NodeMetaRef *ref = checkobject(L, 1);
1655 NodeMetadata *meta = getmeta(ref);
1656 if(meta == NULL) return 0;
1658 meta->resetTextModified();
1659 reportMetadataChange(ref);
1663 // set_string(self, name, var)
1664 static int l_set_string(lua_State *L)
1666 NodeMetaRef *ref = checkobject(L, 1);
1667 NodeMetadata *meta = getmeta(ref);
1668 if(meta == NULL) return 0;
1670 std::string name = lua_tostring(L, 2);
1672 const char *s = lua_tolstring(L, 3, &len);
1673 std::string str(s, len);
1674 meta->setString(name, str);
1675 reportMetadataChange(ref);
1679 // get_string(self, name)
1680 static int l_get_string(lua_State *L)
1682 NodeMetaRef *ref = checkobject(L, 1);
1683 NodeMetadata *meta = getmeta(ref);
1684 if(meta == NULL) return 0;
1686 std::string name = lua_tostring(L, 2);
1687 std::string str = meta->getString(name);
1688 lua_pushlstring(L, str.c_str(), str.size());
1693 NodeMetaRef(v3s16 p, ServerEnvironment *env):
1703 // Creates an NodeMetaRef and leaves it on top of stack
1704 // Not callable from Lua; all references are created on the C side.
1705 static void create(lua_State *L, v3s16 p, ServerEnvironment *env)
1707 NodeMetaRef *o = new NodeMetaRef(p, env);
1708 //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
1709 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1710 luaL_getmetatable(L, className);
1711 lua_setmetatable(L, -2);
1714 static void Register(lua_State *L)
1717 int methodtable = lua_gettop(L);
1718 luaL_newmetatable(L, className);
1719 int metatable = lua_gettop(L);
1721 lua_pushliteral(L, "__metatable");
1722 lua_pushvalue(L, methodtable);
1723 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1725 lua_pushliteral(L, "__index");
1726 lua_pushvalue(L, methodtable);
1727 lua_settable(L, metatable);
1729 lua_pushliteral(L, "__gc");
1730 lua_pushcfunction(L, gc_object);
1731 lua_settable(L, metatable);
1733 lua_pop(L, 1); // drop metatable
1735 luaL_openlib(L, 0, methods, 0); // fill methodtable
1736 lua_pop(L, 1); // drop methodtable
1738 // Cannot be created from Lua
1739 //lua_register(L, className, create_object);
1742 const char NodeMetaRef::className[] = "NodeMetaRef";
1743 const luaL_reg NodeMetaRef::methods[] = {
1744 method(NodeMetaRef, get_type),
1745 method(NodeMetaRef, allows_text_input),
1746 method(NodeMetaRef, set_text),
1747 method(NodeMetaRef, get_text),
1748 method(NodeMetaRef, get_owner),
1749 method(NodeMetaRef, set_infotext),
1750 method(NodeMetaRef, inventory_set_list),
1751 method(NodeMetaRef, inventory_get_list),
1752 method(NodeMetaRef, set_inventory_draw_spec),
1753 method(NodeMetaRef, set_allow_text_input),
1754 method(NodeMetaRef, set_allow_removal),
1755 method(NodeMetaRef, set_enforce_owner),
1756 method(NodeMetaRef, is_inventory_modified),
1757 method(NodeMetaRef, reset_inventory_modified),
1758 method(NodeMetaRef, is_text_modified),
1759 method(NodeMetaRef, reset_text_modified),
1760 method(NodeMetaRef, set_string),
1761 method(NodeMetaRef, get_string),
1772 ServerActiveObject *m_object;
1774 static const char className[];
1775 static const luaL_reg methods[];
1777 static ObjectRef *checkobject(lua_State *L, int narg)
1779 luaL_checktype(L, narg, LUA_TUSERDATA);
1780 void *ud = luaL_checkudata(L, narg, className);
1781 if(!ud) luaL_typerror(L, narg, className);
1782 return *(ObjectRef**)ud; // unbox pointer
1785 static ServerActiveObject* getobject(ObjectRef *ref)
1787 ServerActiveObject *co = ref->m_object;
1791 static LuaEntitySAO* getluaobject(ObjectRef *ref)
1793 ServerActiveObject *obj = getobject(ref);
1796 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1798 return (LuaEntitySAO*)obj;
1801 static ServerRemotePlayer* getplayer(ObjectRef *ref)
1803 ServerActiveObject *obj = getobject(ref);
1806 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
1808 return static_cast<ServerRemotePlayer*>(obj);
1811 // Exported functions
1813 // garbage collector
1814 static int gc_object(lua_State *L) {
1815 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1816 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1822 static int l_remove(lua_State *L)
1824 ObjectRef *ref = checkobject(L, 1);
1825 ServerActiveObject *co = getobject(ref);
1826 if(co == NULL) return 0;
1827 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1828 co->m_removed = true;
1833 // returns: {x=num, y=num, z=num}
1834 static int l_getpos(lua_State *L)
1836 ObjectRef *ref = checkobject(L, 1);
1837 ServerActiveObject *co = getobject(ref);
1838 if(co == NULL) return 0;
1839 v3f pos = co->getBasePosition() / BS;
1841 lua_pushnumber(L, pos.X);
1842 lua_setfield(L, -2, "x");
1843 lua_pushnumber(L, pos.Y);
1844 lua_setfield(L, -2, "y");
1845 lua_pushnumber(L, pos.Z);
1846 lua_setfield(L, -2, "z");
1850 // setpos(self, pos)
1851 static int l_setpos(lua_State *L)
1853 ObjectRef *ref = checkobject(L, 1);
1854 //LuaEntitySAO *co = getluaobject(ref);
1855 ServerActiveObject *co = getobject(ref);
1856 if(co == NULL) return 0;
1858 v3f pos = readFloatPos(L, 2);
1864 // moveto(self, pos, continuous=false)
1865 static int l_moveto(lua_State *L)
1867 ObjectRef *ref = checkobject(L, 1);
1868 //LuaEntitySAO *co = getluaobject(ref);
1869 ServerActiveObject *co = getobject(ref);
1870 if(co == NULL) return 0;
1872 v3f pos = readFloatPos(L, 2);
1874 bool continuous = lua_toboolean(L, 3);
1876 co->moveTo(pos, continuous);
1880 // punch(self, puncher); puncher = an another ObjectRef
1881 static int l_punch(lua_State *L)
1883 ObjectRef *ref = checkobject(L, 1);
1884 ObjectRef *ref2 = checkobject(L, 2);
1885 ServerActiveObject *co = getobject(ref);
1886 ServerActiveObject *co2 = getobject(ref2);
1887 if(co == NULL) return 0;
1888 if(co2 == NULL) return 0;
1894 // right_click(self, clicker); clicker = an another ObjectRef
1895 static int l_right_click(lua_State *L)
1897 ObjectRef *ref = checkobject(L, 1);
1898 ObjectRef *ref2 = checkobject(L, 2);
1899 ServerActiveObject *co = getobject(ref);
1900 ServerActiveObject *co2 = getobject(ref2);
1901 if(co == NULL) return 0;
1902 if(co2 == NULL) return 0;
1904 co->rightClick(co2);
1908 // get_wield_digging_properties(self)
1909 static int l_get_wield_digging_properties(lua_State *L)
1911 ObjectRef *ref = checkobject(L, 1);
1912 ServerActiveObject *co = getobject(ref);
1913 if(co == NULL) return 0;
1915 ToolDiggingProperties prop;
1916 co->getWieldDiggingProperties(&prop);
1917 push_tool_digging_properties(L, prop);
1921 // damage_wielded_item(self, amount)
1922 static int l_damage_wielded_item(lua_State *L)
1924 ObjectRef *ref = checkobject(L, 1);
1925 ServerActiveObject *co = getobject(ref);
1926 if(co == NULL) return 0;
1928 int amount = lua_tonumber(L, 2);
1929 co->damageWieldedItem(amount);
1933 // add_to_inventory(self, itemstring)
1934 // returns: true if item was added, (false, "reason") otherwise
1935 static int l_add_to_inventory(lua_State *L)
1937 ObjectRef *ref = checkobject(L, 1);
1938 luaL_checkstring(L, 2);
1939 ServerActiveObject *co = getobject(ref);
1940 if(co == NULL) return 0;
1942 const char *itemstring = lua_tostring(L, 2);
1943 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1944 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1946 std::istringstream is(itemstring, std::ios::binary);
1947 ServerEnvironment *env = co->getEnv();
1949 IGameDef *gamedef = env->getGameDef();
1951 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1952 if(item->getCount() == 0)
1954 bool added = co->addToInventory(item);
1956 lua_pushboolean(L, added);
1958 lua_pushstring(L, "failed to add item");
1960 } catch(SerializationError &e){
1962 lua_pushboolean(L, false);
1963 lua_pushstring(L, (std::string("Invalid item: ")
1964 + e.what()).c_str());
1969 // add_to_inventory_later(self, itemstring)
1971 static int l_add_to_inventory_later(lua_State *L)
1973 ObjectRef *ref = checkobject(L, 1);
1974 luaL_checkstring(L, 2);
1975 ServerActiveObject *co = getobject(ref);
1976 if(co == NULL) return 0;
1978 const char *itemstring = lua_tostring(L, 2);
1979 infostream<<"ObjectRef::l_add_to_inventory_later(): id="<<co->getId()
1980 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1982 std::istringstream is(itemstring, std::ios::binary);
1983 ServerEnvironment *env = co->getEnv();
1985 IGameDef *gamedef = env->getGameDef();
1986 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1987 infostream<<"item="<<env<<std::endl;
1988 co->addToInventoryLater(item);
1994 // hp = number of hitpoints (2 * number of hearts)
1996 static int l_set_hp(lua_State *L)
1998 ObjectRef *ref = checkobject(L, 1);
1999 luaL_checknumber(L, 2);
2000 ServerActiveObject *co = getobject(ref);
2001 if(co == NULL) return 0;
2002 int hp = lua_tonumber(L, 2);
2003 infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
2004 <<" hp="<<hp<<std::endl;
2012 // returns: number of hitpoints (2 * number of hearts)
2013 // 0 if not applicable to this type of object
2014 static int l_get_hp(lua_State *L)
2016 ObjectRef *ref = checkobject(L, 1);
2017 ServerActiveObject *co = getobject(ref);
2018 if(co == NULL) return 0;
2019 int hp = co->getHP();
2020 infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
2021 <<" hp="<<hp<<std::endl;
2023 lua_pushnumber(L, hp);
2027 /* LuaEntitySAO-only */
2029 // setvelocity(self, {x=num, y=num, z=num})
2030 static int l_setvelocity(lua_State *L)
2032 ObjectRef *ref = checkobject(L, 1);
2033 LuaEntitySAO *co = getluaobject(ref);
2034 if(co == NULL) return 0;
2036 v3f pos = readFloatPos(L, 2);
2038 co->setVelocity(pos);
2042 // setacceleration(self, {x=num, y=num, z=num})
2043 static int l_setacceleration(lua_State *L)
2045 ObjectRef *ref = checkobject(L, 1);
2046 LuaEntitySAO *co = getluaobject(ref);
2047 if(co == NULL) return 0;
2049 v3f pos = readFloatPos(L, 2);
2051 co->setAcceleration(pos);
2055 // getacceleration(self)
2056 static int l_getacceleration(lua_State *L)
2058 ObjectRef *ref = checkobject(L, 1);
2059 LuaEntitySAO *co = getluaobject(ref);
2060 if(co == NULL) return 0;
2062 v3f v = co->getAcceleration();
2067 // settexturemod(self, mod)
2068 static int l_settexturemod(lua_State *L)
2070 ObjectRef *ref = checkobject(L, 1);
2071 LuaEntitySAO *co = getluaobject(ref);
2072 if(co == NULL) return 0;
2074 std::string mod = lua_tostring(L, 2);
2075 co->setTextureMod(mod);
2079 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
2080 // select_horiz_by_yawpitch=false)
2081 static int l_setsprite(lua_State *L)
2083 ObjectRef *ref = checkobject(L, 1);
2084 LuaEntitySAO *co = getluaobject(ref);
2085 if(co == NULL) return 0;
2088 if(!lua_isnil(L, 2))
2089 p = read_v2s16(L, 2);
2091 if(!lua_isnil(L, 3))
2092 num_frames = lua_tonumber(L, 3);
2093 float framelength = 0.2;
2094 if(!lua_isnil(L, 4))
2095 framelength = lua_tonumber(L, 4);
2096 bool select_horiz_by_yawpitch = false;
2097 if(!lua_isnil(L, 5))
2098 select_horiz_by_yawpitch = lua_toboolean(L, 5);
2099 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
2105 // get_player_name(self)
2106 static int l_get_player_name(lua_State *L)
2108 ObjectRef *ref = checkobject(L, 1);
2109 ServerRemotePlayer *player = getplayer(ref);
2115 lua_pushstring(L, player->getName());
2119 // inventory_set_list(self, name, {item1, item2, ...})
2120 static int l_inventory_set_list(lua_State *L)
2122 ObjectRef *ref = checkobject(L, 1);
2123 ServerRemotePlayer *player = getplayer(ref);
2124 if(player == NULL) return 0;
2125 const char *name = lua_tostring(L, 2);
2127 inventory_set_list_from_lua(&player->inventory, name, L, 3,
2128 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2129 player->m_inventory_not_sent = true;
2133 // inventory_get_list(self, name)
2134 static int l_inventory_get_list(lua_State *L)
2136 ObjectRef *ref = checkobject(L, 1);
2137 ServerRemotePlayer *player = getplayer(ref);
2138 if(player == NULL) return 0;
2139 const char *name = lua_tostring(L, 2);
2141 inventory_get_list_to_lua(&player->inventory, name, L);
2145 // get_wielded_itemstring(self)
2146 static int l_get_wielded_itemstring(lua_State *L)
2148 ObjectRef *ref = checkobject(L, 1);
2149 ServerRemotePlayer *player = getplayer(ref);
2150 if(player == NULL) return 0;
2152 InventoryItem *item = player->getWieldedItem();
2157 lua_pushstring(L, item->getItemString().c_str());
2161 // get_wielded_item(self)
2162 static int l_get_wielded_item(lua_State *L)
2164 ObjectRef *ref = checkobject(L, 1);
2165 ServerRemotePlayer *player = getplayer(ref);
2166 if(player == NULL) return 0;
2168 InventoryItem *item0 = player->getWieldedItem();
2173 if(std::string("MaterialItem") == item0->getName()){
2174 MaterialItem *item = (MaterialItem*)item0;
2176 lua_pushstring(L, "NodeItem");
2177 lua_setfield(L, -2, "type");
2178 lua_pushstring(L, item->getNodeName().c_str());
2179 lua_setfield(L, -2, "name");
2181 else if(std::string("CraftItem") == item0->getName()){
2182 CraftItem *item = (CraftItem*)item0;
2184 lua_pushstring(L, "CraftItem");
2185 lua_setfield(L, -2, "type");
2186 lua_pushstring(L, item->getSubName().c_str());
2187 lua_setfield(L, -2, "name");
2189 else if(std::string("ToolItem") == item0->getName()){
2190 ToolItem *item = (ToolItem*)item0;
2192 lua_pushstring(L, "ToolItem");
2193 lua_setfield(L, -2, "type");
2194 lua_pushstring(L, item->getToolName().c_str());
2195 lua_setfield(L, -2, "name");
2196 lua_pushstring(L, itos(item->getWear()).c_str());
2197 lua_setfield(L, -2, "wear");
2200 errorstream<<"l_get_wielded_item: Unknown item name: \""
2201 <<item0->getName()<<"\""<<std::endl;
2208 ObjectRef(ServerActiveObject *object):
2211 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2217 infostream<<"ObjectRef destructing for id="
2218 <<m_object->getId()<<std::endl;
2220 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
2223 // Creates an ObjectRef and leaves it on top of stack
2224 // Not callable from Lua; all references are created on the C side.
2225 static void create(lua_State *L, ServerActiveObject *object)
2227 ObjectRef *o = new ObjectRef(object);
2228 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2229 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2230 luaL_getmetatable(L, className);
2231 lua_setmetatable(L, -2);
2234 static void set_null(lua_State *L)
2236 ObjectRef *o = checkobject(L, -1);
2240 static void Register(lua_State *L)
2243 int methodtable = lua_gettop(L);
2244 luaL_newmetatable(L, className);
2245 int metatable = lua_gettop(L);
2247 lua_pushliteral(L, "__metatable");
2248 lua_pushvalue(L, methodtable);
2249 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2251 lua_pushliteral(L, "__index");
2252 lua_pushvalue(L, methodtable);
2253 lua_settable(L, metatable);
2255 lua_pushliteral(L, "__gc");
2256 lua_pushcfunction(L, gc_object);
2257 lua_settable(L, metatable);
2259 lua_pop(L, 1); // drop metatable
2261 luaL_openlib(L, 0, methods, 0); // fill methodtable
2262 lua_pop(L, 1); // drop methodtable
2264 // Cannot be created from Lua
2265 //lua_register(L, className, create_object);
2268 const char ObjectRef::className[] = "ObjectRef";
2269 const luaL_reg ObjectRef::methods[] = {
2270 // ServerActiveObject
2271 method(ObjectRef, remove),
2272 method(ObjectRef, getpos),
2273 method(ObjectRef, setpos),
2274 method(ObjectRef, moveto),
2275 method(ObjectRef, punch),
2276 method(ObjectRef, right_click),
2277 method(ObjectRef, get_wield_digging_properties),
2278 method(ObjectRef, damage_wielded_item),
2279 method(ObjectRef, add_to_inventory),
2280 method(ObjectRef, add_to_inventory_later),
2281 method(ObjectRef, set_hp),
2282 method(ObjectRef, get_hp),
2283 // LuaEntitySAO-only
2284 method(ObjectRef, setvelocity),
2285 method(ObjectRef, setacceleration),
2286 method(ObjectRef, getacceleration),
2287 method(ObjectRef, settexturemod),
2288 method(ObjectRef, setsprite),
2290 method(ObjectRef, get_player_name),
2291 method(ObjectRef, inventory_set_list),
2292 method(ObjectRef, inventory_get_list),
2293 method(ObjectRef, get_wielded_itemstring),
2294 method(ObjectRef, get_wielded_item),
2298 // Creates a new anonymous reference if id=0
2299 static void objectref_get_or_create(lua_State *L,
2300 ServerActiveObject *cobj)
2302 if(cobj->getId() == 0){
2303 ObjectRef::create(L, cobj);
2305 objectref_get(L, cobj->getId());
2316 ServerEnvironment *m_env;
2318 static const char className[];
2319 static const luaL_reg methods[];
2321 static EnvRef *checkobject(lua_State *L, int narg)
2323 luaL_checktype(L, narg, LUA_TUSERDATA);
2324 void *ud = luaL_checkudata(L, narg, className);
2325 if(!ud) luaL_typerror(L, narg, className);
2326 return *(EnvRef**)ud; // unbox pointer
2329 // Exported functions
2331 // EnvRef:add_node(pos, node)
2332 // pos = {x=num, y=num, z=num}
2333 static int l_add_node(lua_State *L)
2335 //infostream<<"EnvRef::l_add_node()"<<std::endl;
2336 EnvRef *o = checkobject(L, 1);
2337 ServerEnvironment *env = o->m_env;
2338 if(env == NULL) return 0;
2340 v3s16 pos = readpos(L, 2);
2342 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
2344 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
2345 lua_pushboolean(L, succeeded);
2349 // EnvRef:remove_node(pos)
2350 // pos = {x=num, y=num, z=num}
2351 static int l_remove_node(lua_State *L)
2353 //infostream<<"EnvRef::l_remove_node()"<<std::endl;
2354 EnvRef *o = checkobject(L, 1);
2355 ServerEnvironment *env = o->m_env;
2356 if(env == NULL) return 0;
2358 v3s16 pos = readpos(L, 2);
2360 bool succeeded = env->getMap().removeNodeWithEvent(pos);
2361 lua_pushboolean(L, succeeded);
2365 // EnvRef:get_node(pos)
2366 // pos = {x=num, y=num, z=num}
2367 static int l_get_node(lua_State *L)
2369 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2370 EnvRef *o = checkobject(L, 1);
2371 ServerEnvironment *env = o->m_env;
2372 if(env == NULL) return 0;
2374 v3s16 pos = readpos(L, 2);
2376 MapNode n = env->getMap().getNodeNoEx(pos);
2378 pushnode(L, n, env->getGameDef()->ndef());
2382 // EnvRef:get_node_or_nil(pos)
2383 // pos = {x=num, y=num, z=num}
2384 static int l_get_node_or_nil(lua_State *L)
2386 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2387 EnvRef *o = checkobject(L, 1);
2388 ServerEnvironment *env = o->m_env;
2389 if(env == NULL) return 0;
2391 v3s16 pos = readpos(L, 2);
2394 MapNode n = env->getMap().getNode(pos);
2396 pushnode(L, n, env->getGameDef()->ndef());
2398 } catch(InvalidPositionException &e)
2405 // EnvRef:add_luaentity(pos, entityname)
2406 // pos = {x=num, y=num, z=num}
2407 static int l_add_luaentity(lua_State *L)
2409 //infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
2410 EnvRef *o = checkobject(L, 1);
2411 ServerEnvironment *env = o->m_env;
2412 if(env == NULL) return 0;
2414 v3f pos = readFloatPos(L, 2);
2416 const char *name = lua_tostring(L, 3);
2418 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
2419 env->addActiveObject(obj);
2423 // EnvRef:add_item(pos, inventorystring)
2424 // pos = {x=num, y=num, z=num}
2425 static int l_add_item(lua_State *L)
2427 infostream<<"EnvRef::l_add_item()"<<std::endl;
2428 EnvRef *o = checkobject(L, 1);
2429 ServerEnvironment *env = o->m_env;
2430 if(env == NULL) return 0;
2432 v3f pos = readFloatPos(L, 2);
2434 const char *inventorystring = lua_tostring(L, 3);
2436 ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring);
2437 env->addActiveObject(obj);
2441 // EnvRef:add_rat(pos)
2442 // pos = {x=num, y=num, z=num}
2443 static int l_add_rat(lua_State *L)
2445 infostream<<"EnvRef::l_add_rat()"<<std::endl;
2446 EnvRef *o = checkobject(L, 1);
2447 ServerEnvironment *env = o->m_env;
2448 if(env == NULL) return 0;
2450 v3f pos = readFloatPos(L, 2);
2452 ServerActiveObject *obj = new RatSAO(env, pos);
2453 env->addActiveObject(obj);
2457 // EnvRef:add_firefly(pos)
2458 // pos = {x=num, y=num, z=num}
2459 static int l_add_firefly(lua_State *L)
2461 infostream<<"EnvRef::l_add_firefly()"<<std::endl;
2462 EnvRef *o = checkobject(L, 1);
2463 ServerEnvironment *env = o->m_env;
2464 if(env == NULL) return 0;
2466 v3f pos = readFloatPos(L, 2);
2468 ServerActiveObject *obj = new FireflySAO(env, pos);
2469 env->addActiveObject(obj);
2473 // EnvRef:get_meta(pos)
2474 static int l_get_meta(lua_State *L)
2476 //infostream<<"EnvRef::l_get_meta()"<<std::endl;
2477 EnvRef *o = checkobject(L, 1);
2478 ServerEnvironment *env = o->m_env;
2479 if(env == NULL) return 0;
2481 v3s16 p = readpos(L, 2);
2482 NodeMetaRef::create(L, p, env);
2486 // EnvRef:get_player_by_name(name)
2487 static int l_get_player_by_name(lua_State *L)
2489 EnvRef *o = checkobject(L, 1);
2490 ServerEnvironment *env = o->m_env;
2491 if(env == NULL) return 0;
2493 const char *name = lua_tostring(L, 2);
2494 ServerRemotePlayer *player =
2495 static_cast<ServerRemotePlayer*>(env->getPlayer(name));
2500 // Put player on stack
2501 objectref_get_or_create(L, player);
2505 static int gc_object(lua_State *L) {
2506 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
2512 EnvRef(ServerEnvironment *env):
2515 infostream<<"EnvRef created"<<std::endl;
2520 infostream<<"EnvRef destructing"<<std::endl;
2523 // Creates an EnvRef and leaves it on top of stack
2524 // Not callable from Lua; all references are created on the C side.
2525 static void create(lua_State *L, ServerEnvironment *env)
2527 EnvRef *o = new EnvRef(env);
2528 //infostream<<"EnvRef::create: o="<<o<<std::endl;
2529 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2530 luaL_getmetatable(L, className);
2531 lua_setmetatable(L, -2);
2534 static void set_null(lua_State *L)
2536 EnvRef *o = checkobject(L, -1);
2540 static void Register(lua_State *L)
2543 int methodtable = lua_gettop(L);
2544 luaL_newmetatable(L, className);
2545 int metatable = lua_gettop(L);
2547 lua_pushliteral(L, "__metatable");
2548 lua_pushvalue(L, methodtable);
2549 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2551 lua_pushliteral(L, "__index");
2552 lua_pushvalue(L, methodtable);
2553 lua_settable(L, metatable);
2555 lua_pushliteral(L, "__gc");
2556 lua_pushcfunction(L, gc_object);
2557 lua_settable(L, metatable);
2559 lua_pop(L, 1); // drop metatable
2561 luaL_openlib(L, 0, methods, 0); // fill methodtable
2562 lua_pop(L, 1); // drop methodtable
2564 // Cannot be created from Lua
2565 //lua_register(L, className, create_object);
2568 const char EnvRef::className[] = "EnvRef";
2569 const luaL_reg EnvRef::methods[] = {
2570 method(EnvRef, add_node),
2571 method(EnvRef, remove_node),
2572 method(EnvRef, get_node),
2573 method(EnvRef, get_node_or_nil),
2574 method(EnvRef, add_luaentity),
2575 method(EnvRef, add_item),
2576 method(EnvRef, add_rat),
2577 method(EnvRef, add_firefly),
2578 method(EnvRef, get_meta),
2579 method(EnvRef, get_player_by_name),
2584 Main export function
2587 void scriptapi_export(lua_State *L, Server *server)
2590 assert(lua_checkstack(L, 20));
2591 infostream<<"scriptapi_export"<<std::endl;
2592 StackUnroller stack_unroller(L);
2594 // Store server as light userdata in registry
2595 lua_pushlightuserdata(L, server);
2596 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
2598 // Store nil as minetest_nodedef_defaults in registry
2600 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
2602 // Register global functions in table minetest
2604 luaL_register(L, NULL, minetest_f);
2605 lua_setglobal(L, "minetest");
2607 // Get the main minetest table
2608 lua_getglobal(L, "minetest");
2610 // Add tables to minetest
2613 lua_setfield(L, -2, "registered_nodes");
2615 lua_setfield(L, -2, "registered_entities");
2617 lua_setfield(L, -2, "registered_craftitems");
2619 lua_setfield(L, -2, "registered_abms");
2622 lua_setfield(L, -2, "object_refs");
2624 lua_setfield(L, -2, "luaentities");
2626 // Create entity prototype
2627 luaL_newmetatable(L, "minetest.entity");
2628 // metatable.__index = metatable
2629 lua_pushvalue(L, -1); // Duplicate metatable
2630 lua_setfield(L, -2, "__index");
2631 // Put functions in metatable
2632 luaL_register(L, NULL, minetest_entity_m);
2633 // Put other stuff in metatable
2635 // Register reference wrappers
2636 NodeMetaRef::Register(L);
2637 EnvRef::Register(L);
2638 ObjectRef::Register(L);
2641 bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
2642 const std::string &modname)
2644 ModNameStorer modnamestorer(L, modname);
2646 bool success = false;
2649 success = script_load(L, scriptpath.c_str());
2652 errorstream<<"Error loading mod \""<<modname
2653 <<"\": "<<e.what()<<std::endl;
2659 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
2662 assert(lua_checkstack(L, 20));
2663 infostream<<"scriptapi_add_environment"<<std::endl;
2664 StackUnroller stack_unroller(L);
2666 // Create EnvRef on stack
2667 EnvRef::create(L, env);
2668 int envref = lua_gettop(L);
2670 // minetest.env = envref
2671 lua_getglobal(L, "minetest");
2672 luaL_checktype(L, -1, LUA_TTABLE);
2673 lua_pushvalue(L, envref);
2674 lua_setfield(L, -2, "env");
2676 // Store environment as light userdata in registry
2677 lua_pushlightuserdata(L, env);
2678 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
2681 Add ActiveBlockModifiers to environment
2684 // Get minetest.registered_abms
2685 lua_getglobal(L, "minetest");
2686 lua_getfield(L, -1, "registered_abms");
2687 luaL_checktype(L, -1, LUA_TTABLE);
2688 int registered_abms = lua_gettop(L);
2690 if(lua_istable(L, registered_abms)){
2691 int table = lua_gettop(L);
2693 while(lua_next(L, table) != 0){
2694 // key at index -2 and value at index -1
2695 int id = lua_tonumber(L, -2);
2696 int current_abm = lua_gettop(L);
2698 std::set<std::string> trigger_contents;
2699 lua_getfield(L, current_abm, "nodenames");
2700 if(lua_istable(L, -1)){
2701 int table = lua_gettop(L);
2703 while(lua_next(L, table) != 0){
2704 // key at index -2 and value at index -1
2705 luaL_checktype(L, -1, LUA_TSTRING);
2706 trigger_contents.insert(lua_tostring(L, -1));
2707 // removes value, keeps key for next iteration
2710 } else if(lua_isstring(L, -1)){
2711 trigger_contents.insert(lua_tostring(L, -1));
2715 std::set<std::string> required_neighbors;
2716 lua_getfield(L, current_abm, "neighbors");
2717 if(lua_istable(L, -1)){
2718 int table = lua_gettop(L);
2720 while(lua_next(L, table) != 0){
2721 // key at index -2 and value at index -1
2722 luaL_checktype(L, -1, LUA_TSTRING);
2723 required_neighbors.insert(lua_tostring(L, -1));
2724 // removes value, keeps key for next iteration
2727 } else if(lua_isstring(L, -1)){
2728 required_neighbors.insert(lua_tostring(L, -1));
2732 float trigger_interval = 10.0;
2733 getfloatfield(L, current_abm, "interval", trigger_interval);
2735 int trigger_chance = 50;
2736 getintfield(L, current_abm, "chance", trigger_chance);
2738 LuaABM *abm = new LuaABM(L, id, trigger_contents,
2739 required_neighbors, trigger_interval, trigger_chance);
2741 env->addActiveBlockModifier(abm);
2743 // removes value, keeps key for next iteration
2751 // Dump stack top with the dump2 function
2752 static void dump2(lua_State *L, const char *name)
2754 // Dump object (debug)
2755 lua_getglobal(L, "dump2");
2756 luaL_checktype(L, -1, LUA_TFUNCTION);
2757 lua_pushvalue(L, -2); // Get previous stack top as first parameter
2758 lua_pushstring(L, name);
2759 if(lua_pcall(L, 2, 0, 0))
2760 script_error(L, "error: %s", lua_tostring(L, -1));
2768 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
2771 assert(lua_checkstack(L, 20));
2772 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
2773 StackUnroller stack_unroller(L);
2775 // Create object on stack
2776 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
2777 int object = lua_gettop(L);
2779 // Get minetest.object_refs table
2780 lua_getglobal(L, "minetest");
2781 lua_getfield(L, -1, "object_refs");
2782 luaL_checktype(L, -1, LUA_TTABLE);
2783 int objectstable = lua_gettop(L);
2785 // object_refs[id] = object
2786 lua_pushnumber(L, cobj->getId()); // Push id
2787 lua_pushvalue(L, object); // Copy object to top of stack
2788 lua_settable(L, objectstable);
2791 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
2794 assert(lua_checkstack(L, 20));
2795 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
2796 StackUnroller stack_unroller(L);
2798 // Get minetest.object_refs table
2799 lua_getglobal(L, "minetest");
2800 lua_getfield(L, -1, "object_refs");
2801 luaL_checktype(L, -1, LUA_TTABLE);
2802 int objectstable = lua_gettop(L);
2804 // Get object_refs[id]
2805 lua_pushnumber(L, cobj->getId()); // Push id
2806 lua_gettable(L, objectstable);
2807 // Set object reference to NULL
2808 ObjectRef::set_null(L);
2809 lua_pop(L, 1); // pop object
2811 // Set object_refs[id] = nil
2812 lua_pushnumber(L, cobj->getId()); // Push id
2814 lua_settable(L, objectstable);
2817 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
2818 const std::string &message)
2821 assert(lua_checkstack(L, 20));
2822 StackUnroller stack_unroller(L);
2824 // Get minetest.registered_on_chat_messages
2825 lua_getglobal(L, "minetest");
2826 lua_getfield(L, -1, "registered_on_chat_messages");
2827 luaL_checktype(L, -1, LUA_TTABLE);
2828 int table = lua_gettop(L);
2831 while(lua_next(L, table) != 0){
2832 // key at index -2 and value at index -1
2833 luaL_checktype(L, -1, LUA_TFUNCTION);
2835 lua_pushstring(L, name.c_str());
2836 lua_pushstring(L, message.c_str());
2837 if(lua_pcall(L, 2, 1, 0))
2838 script_error(L, "error: %s", lua_tostring(L, -1));
2839 bool ate = lua_toboolean(L, -1);
2843 // value removed, keep key for next iteration
2852 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
2855 assert(lua_checkstack(L, 20));
2856 StackUnroller stack_unroller(L);
2858 // Get minetest.registered_on_newplayers
2859 lua_getglobal(L, "minetest");
2860 lua_getfield(L, -1, "registered_on_newplayers");
2861 luaL_checktype(L, -1, LUA_TTABLE);
2862 int table = lua_gettop(L);
2865 while(lua_next(L, table) != 0){
2866 // key at index -2 and value at index -1
2867 luaL_checktype(L, -1, LUA_TFUNCTION);
2869 objectref_get_or_create(L, player);
2870 if(lua_pcall(L, 1, 0, 0))
2871 script_error(L, "error: %s", lua_tostring(L, -1));
2872 // value removed, keep key for next iteration
2875 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
2878 assert(lua_checkstack(L, 20));
2879 StackUnroller stack_unroller(L);
2881 bool positioning_handled_by_some = false;
2883 // Get minetest.registered_on_respawnplayers
2884 lua_getglobal(L, "minetest");
2885 lua_getfield(L, -1, "registered_on_respawnplayers");
2886 luaL_checktype(L, -1, LUA_TTABLE);
2887 int table = lua_gettop(L);
2890 while(lua_next(L, table) != 0){
2891 // key at index -2 and value at index -1
2892 luaL_checktype(L, -1, LUA_TFUNCTION);
2894 objectref_get_or_create(L, player);
2895 if(lua_pcall(L, 1, 1, 0))
2896 script_error(L, "error: %s", lua_tostring(L, -1));
2897 bool positioning_handled = lua_toboolean(L, -1);
2899 if(positioning_handled)
2900 positioning_handled_by_some = true;
2901 // value removed, keep key for next iteration
2903 return positioning_handled_by_some;
2906 void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
2908 lua_getglobal(L, "minetest");
2909 lua_getfield(L, -1, "creative_inventory");
2910 luaL_checktype(L, -1, LUA_TTABLE);
2911 inventory_set_list_from_lua(&player->inventory, "main", L, -1,
2912 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2919 static void pushPointedThing(lua_State *L, const PointedThing& pointed)
2922 if(pointed.type == POINTEDTHING_NODE)
2924 lua_pushstring(L, "node");
2925 lua_setfield(L, -2, "type");
2926 pushpos(L, pointed.node_undersurface);
2927 lua_setfield(L, -2, "under");
2928 pushpos(L, pointed.node_abovesurface);
2929 lua_setfield(L, -2, "above");
2931 else if(pointed.type == POINTEDTHING_OBJECT)
2933 lua_pushstring(L, "object");
2934 lua_setfield(L, -2, "type");
2935 objectref_get(L, pointed.object_id);
2936 lua_setfield(L, -2, "ref");
2940 lua_pushstring(L, "nothing");
2941 lua_setfield(L, -2, "type");
2945 void scriptapi_add_craftitem(lua_State *L, const char *name)
2947 StackUnroller stack_unroller(L);
2948 assert(lua_gettop(L) > 0);
2950 // Set minetest.registered_craftitems[name] = table on top of stack
2951 lua_getglobal(L, "minetest");
2952 lua_getfield(L, -1, "registered_craftitems");
2953 luaL_checktype(L, -1, LUA_TTABLE);
2954 lua_pushvalue(L, -3); // push another reference to the table to be registered
2955 lua_setfield(L, -2, name); // set minetest.registered_craftitems[name]
2958 static bool get_craftitem_callback(lua_State *L, const char *name,
2959 const char *callbackname)
2961 // Get minetest.registered_craftitems[name][callbackname]
2962 // If that is nil or on error, return false and stack is unchanged
2963 // If that is a function, returns true and pushes the
2964 // function onto the stack
2966 lua_getglobal(L, "minetest");
2967 lua_getfield(L, -1, "registered_craftitems");
2969 luaL_checktype(L, -1, LUA_TTABLE);
2970 lua_getfield(L, -1, name);
2972 // Should be a table
2973 if(lua_type(L, -1) != LUA_TTABLE)
2975 errorstream<<"CraftItem name \""<<name<<"\" not defined"<<std::endl;
2979 lua_getfield(L, -1, callbackname);
2981 // Should be a function or nil
2982 if(lua_type(L, -1) == LUA_TFUNCTION)
2986 else if(lua_isnil(L, -1))
2993 errorstream<<"CraftItem name \""<<name<<"\" callback \""
2994 <<callbackname<<" is not a function"<<std::endl;
3000 bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
3001 ServerActiveObject *dropper, v3f pos,
3002 bool &callback_exists)
3005 assert(lua_checkstack(L, 20));
3006 //infostream<<"scriptapi_craftitem_on_drop"<<std::endl;
3007 StackUnroller stack_unroller(L);
3009 bool result = false;
3010 callback_exists = get_craftitem_callback(L, name, "on_drop");
3014 lua_pushstring(L, name);
3015 objectref_get_or_create(L, dropper);
3016 pushFloatPos(L, pos);
3017 if(lua_pcall(L, 3, 1, 0))
3018 script_error(L, "error: %s", lua_tostring(L, -1));
3019 result = lua_toboolean(L, -1);
3024 bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
3025 ServerActiveObject *placer, v3f pos,
3026 bool &callback_exists)
3029 assert(lua_checkstack(L, 20));
3030 //infostream<<"scriptapi_craftitem_on_place_on_ground"<<std::endl;
3031 StackUnroller stack_unroller(L);
3033 bool result = false;
3034 callback_exists = get_craftitem_callback(L, name, "on_place_on_ground");
3038 lua_pushstring(L, name);
3039 objectref_get_or_create(L, placer);
3040 pushFloatPos(L, pos);
3041 if(lua_pcall(L, 3, 1, 0))
3042 script_error(L, "error: %s", lua_tostring(L, -1));
3043 result = lua_toboolean(L, -1);
3048 bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
3049 ServerActiveObject *user, const PointedThing& pointed,
3050 bool &callback_exists)
3053 assert(lua_checkstack(L, 20));
3054 //infostream<<"scriptapi_craftitem_on_use"<<std::endl;
3055 StackUnroller stack_unroller(L);
3057 bool result = false;
3058 callback_exists = get_craftitem_callback(L, name, "on_use");
3062 lua_pushstring(L, name);
3063 objectref_get_or_create(L, user);
3064 pushPointedThing(L, pointed);
3065 if(lua_pcall(L, 3, 1, 0))
3066 script_error(L, "error: %s", lua_tostring(L, -1));
3067 result = lua_toboolean(L, -1);
3076 void scriptapi_environment_step(lua_State *L, float dtime)
3079 assert(lua_checkstack(L, 20));
3080 //infostream<<"scriptapi_environment_step"<<std::endl;
3081 StackUnroller stack_unroller(L);
3083 // Get minetest.registered_globalsteps
3084 lua_getglobal(L, "minetest");
3085 lua_getfield(L, -1, "registered_globalsteps");
3086 luaL_checktype(L, -1, LUA_TTABLE);
3087 int table = lua_gettop(L);
3090 while(lua_next(L, table) != 0){
3091 // key at index -2 and value at index -1
3092 luaL_checktype(L, -1, LUA_TFUNCTION);
3094 lua_pushnumber(L, dtime);
3095 if(lua_pcall(L, 1, 0, 0))
3096 script_error(L, "error: %s", lua_tostring(L, -1));
3097 // value removed, keep key for next iteration
3101 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
3102 ServerActiveObject *placer)
3105 assert(lua_checkstack(L, 20));
3106 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
3107 StackUnroller stack_unroller(L);
3109 // Get server from registry
3110 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3111 Server *server = (Server*)lua_touserdata(L, -1);
3112 // And get the writable node definition manager from the server
3113 IWritableNodeDefManager *ndef =
3114 server->getWritableNodeDefManager();
3116 // Get minetest.registered_on_placenodes
3117 lua_getglobal(L, "minetest");
3118 lua_getfield(L, -1, "registered_on_placenodes");
3119 luaL_checktype(L, -1, LUA_TTABLE);
3120 int table = lua_gettop(L);
3123 while(lua_next(L, table) != 0){
3124 // key at index -2 and value at index -1
3125 luaL_checktype(L, -1, LUA_TFUNCTION);
3128 pushnode(L, newnode, ndef);
3129 objectref_get_or_create(L, placer);
3130 if(lua_pcall(L, 3, 0, 0))
3131 script_error(L, "error: %s", lua_tostring(L, -1));
3132 // value removed, keep key for next iteration
3136 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
3137 ServerActiveObject *digger)
3140 assert(lua_checkstack(L, 20));
3141 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
3142 StackUnroller stack_unroller(L);
3144 // Get server from registry
3145 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3146 Server *server = (Server*)lua_touserdata(L, -1);
3147 // And get the writable node definition manager from the server
3148 IWritableNodeDefManager *ndef =
3149 server->getWritableNodeDefManager();
3151 // Get minetest.registered_on_dignodes
3152 lua_getglobal(L, "minetest");
3153 lua_getfield(L, -1, "registered_on_dignodes");
3154 luaL_checktype(L, -1, LUA_TTABLE);
3155 int table = lua_gettop(L);
3158 while(lua_next(L, table) != 0){
3159 // key at index -2 and value at index -1
3160 luaL_checktype(L, -1, LUA_TFUNCTION);
3163 pushnode(L, oldnode, ndef);
3164 objectref_get_or_create(L, digger);
3165 if(lua_pcall(L, 3, 0, 0))
3166 script_error(L, "error: %s", lua_tostring(L, -1));
3167 // value removed, keep key for next iteration
3171 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
3172 ServerActiveObject *puncher)
3175 assert(lua_checkstack(L, 20));
3176 //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
3177 StackUnroller stack_unroller(L);
3179 // Get server from registry
3180 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3181 Server *server = (Server*)lua_touserdata(L, -1);
3182 // And get the writable node definition manager from the server
3183 IWritableNodeDefManager *ndef =
3184 server->getWritableNodeDefManager();
3186 // Get minetest.registered_on_punchnodes
3187 lua_getglobal(L, "minetest");
3188 lua_getfield(L, -1, "registered_on_punchnodes");
3189 luaL_checktype(L, -1, LUA_TTABLE);
3190 int table = lua_gettop(L);
3193 while(lua_next(L, table) != 0){
3194 // key at index -2 and value at index -1
3195 luaL_checktype(L, -1, LUA_TFUNCTION);
3198 pushnode(L, node, ndef);
3199 objectref_get_or_create(L, puncher);
3200 if(lua_pcall(L, 3, 0, 0))
3201 script_error(L, "error: %s", lua_tostring(L, -1));
3202 // value removed, keep key for next iteration
3206 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
3209 assert(lua_checkstack(L, 20));
3210 //infostream<<"scriptapi_environment_on_generated"<<std::endl;
3211 StackUnroller stack_unroller(L);
3213 // Get minetest.registered_on_generateds
3214 lua_getglobal(L, "minetest");
3215 lua_getfield(L, -1, "registered_on_generateds");
3216 luaL_checktype(L, -1, LUA_TTABLE);
3217 int table = lua_gettop(L);
3220 while(lua_next(L, table) != 0){
3221 // key at index -2 and value at index -1
3222 luaL_checktype(L, -1, LUA_TFUNCTION);
3226 if(lua_pcall(L, 2, 0, 0))
3227 script_error(L, "error: %s", lua_tostring(L, -1));
3228 // value removed, keep key for next iteration
3236 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
3237 const std::string &staticdata)
3240 assert(lua_checkstack(L, 20));
3241 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
3242 <<name<<"\""<<std::endl;
3243 StackUnroller stack_unroller(L);
3245 // Get minetest.registered_entities[name]
3246 lua_getglobal(L, "minetest");
3247 lua_getfield(L, -1, "registered_entities");
3248 luaL_checktype(L, -1, LUA_TTABLE);
3249 lua_pushstring(L, name);
3250 lua_gettable(L, -2);
3251 // Should be a table, which we will use as a prototype
3252 //luaL_checktype(L, -1, LUA_TTABLE);
3253 if(lua_type(L, -1) != LUA_TTABLE){
3254 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
3257 int prototype_table = lua_gettop(L);
3258 //dump2(L, "prototype_table");
3260 // Create entity object
3262 int object = lua_gettop(L);
3264 // Set object metatable
3265 lua_pushvalue(L, prototype_table);
3266 lua_setmetatable(L, -2);
3268 // Add object reference
3269 // This should be userdata with metatable ObjectRef
3270 objectref_get(L, id);
3271 luaL_checktype(L, -1, LUA_TUSERDATA);
3272 if(!luaL_checkudata(L, -1, "ObjectRef"))
3273 luaL_typerror(L, -1, "ObjectRef");
3274 lua_setfield(L, -2, "object");
3276 // minetest.luaentities[id] = object
3277 lua_getglobal(L, "minetest");
3278 lua_getfield(L, -1, "luaentities");
3279 luaL_checktype(L, -1, LUA_TTABLE);
3280 lua_pushnumber(L, id); // Push id
3281 lua_pushvalue(L, object); // Copy object to top of stack
3282 lua_settable(L, -3);
3284 // Get on_activate function
3285 lua_pushvalue(L, object);
3286 lua_getfield(L, -1, "on_activate");
3287 if(!lua_isnil(L, -1)){
3288 luaL_checktype(L, -1, LUA_TFUNCTION);
3289 lua_pushvalue(L, object); // self
3290 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
3291 // Call with 2 arguments, 0 results
3292 if(lua_pcall(L, 2, 0, 0))
3293 script_error(L, "error running function %s:on_activate: %s\n",
3294 name, lua_tostring(L, -1));
3300 void scriptapi_luaentity_rm(lua_State *L, u16 id)
3303 assert(lua_checkstack(L, 20));
3304 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
3306 // Get minetest.luaentities table
3307 lua_getglobal(L, "minetest");
3308 lua_getfield(L, -1, "luaentities");
3309 luaL_checktype(L, -1, LUA_TTABLE);
3310 int objectstable = lua_gettop(L);
3312 // Set luaentities[id] = nil
3313 lua_pushnumber(L, id); // Push id
3315 lua_settable(L, objectstable);
3317 lua_pop(L, 2); // pop luaentities, minetest
3320 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
3323 assert(lua_checkstack(L, 20));
3324 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
3325 StackUnroller stack_unroller(L);
3327 // Get minetest.luaentities[id]
3328 luaentity_get(L, id);
3329 int object = lua_gettop(L);
3331 // Get get_staticdata function
3332 lua_pushvalue(L, object);
3333 lua_getfield(L, -1, "get_staticdata");
3334 if(lua_isnil(L, -1))
3337 luaL_checktype(L, -1, LUA_TFUNCTION);
3338 lua_pushvalue(L, object); // self
3339 // Call with 1 arguments, 1 results
3340 if(lua_pcall(L, 1, 1, 0))
3341 script_error(L, "error running function get_staticdata: %s\n",
3342 lua_tostring(L, -1));
3345 const char *s = lua_tolstring(L, -1, &len);
3346 return std::string(s, len);
3349 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
3350 LuaEntityProperties *prop)
3353 assert(lua_checkstack(L, 20));
3354 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
3355 StackUnroller stack_unroller(L);
3357 // Get minetest.luaentities[id]
3358 luaentity_get(L, id);
3359 //int object = lua_gettop(L);
3363 getboolfield(L, -1, "physical", prop->physical);
3365 getfloatfield(L, -1, "weight", prop->weight);
3367 lua_getfield(L, -1, "collisionbox");
3368 if(lua_istable(L, -1))
3369 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
3372 getstringfield(L, -1, "visual", prop->visual);
3374 lua_getfield(L, -1, "visual_size");
3375 if(lua_istable(L, -1))
3376 prop->visual_size = read_v2f(L, -1);
3379 lua_getfield(L, -1, "textures");
3380 if(lua_istable(L, -1)){
3381 prop->textures.clear();
3382 int table = lua_gettop(L);
3384 while(lua_next(L, table) != 0){
3385 // key at index -2 and value at index -1
3386 if(lua_isstring(L, -1))
3387 prop->textures.push_back(lua_tostring(L, -1));
3389 prop->textures.push_back("");
3390 // removes value, keeps key for next iteration
3396 lua_getfield(L, -1, "spritediv");
3397 if(lua_istable(L, -1))
3398 prop->spritediv = read_v2s16(L, -1);
3401 lua_getfield(L, -1, "initial_sprite_basepos");
3402 if(lua_istable(L, -1))
3403 prop->initial_sprite_basepos = read_v2s16(L, -1);
3407 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
3410 assert(lua_checkstack(L, 20));
3411 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3412 StackUnroller stack_unroller(L);
3414 // Get minetest.luaentities[id]
3415 luaentity_get(L, id);
3416 int object = lua_gettop(L);
3417 // State: object is at top of stack
3418 // Get step function
3419 lua_getfield(L, -1, "on_step");
3420 if(lua_isnil(L, -1))
3422 luaL_checktype(L, -1, LUA_TFUNCTION);
3423 lua_pushvalue(L, object); // self
3424 lua_pushnumber(L, dtime); // dtime
3425 // Call with 2 arguments, 0 results
3426 if(lua_pcall(L, 2, 0, 0))
3427 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
3430 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
3431 void scriptapi_luaentity_punch(lua_State *L, u16 id,
3432 ServerActiveObject *puncher, float time_from_last_punch)
3435 assert(lua_checkstack(L, 20));
3436 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3437 StackUnroller stack_unroller(L);
3439 // Get minetest.luaentities[id]
3440 luaentity_get(L, id);
3441 int object = lua_gettop(L);
3442 // State: object is at top of stack
3444 lua_getfield(L, -1, "on_punch");
3445 if(lua_isnil(L, -1))
3447 luaL_checktype(L, -1, LUA_TFUNCTION);
3448 lua_pushvalue(L, object); // self
3449 objectref_get_or_create(L, puncher); // Clicker reference
3450 lua_pushnumber(L, time_from_last_punch);
3451 // Call with 2 arguments, 0 results
3452 if(lua_pcall(L, 3, 0, 0))
3453 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
3456 // Calls entity:on_rightclick(ObjectRef clicker)
3457 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
3458 ServerActiveObject *clicker)
3461 assert(lua_checkstack(L, 20));
3462 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3463 StackUnroller stack_unroller(L);
3465 // Get minetest.luaentities[id]
3466 luaentity_get(L, id);
3467 int object = lua_gettop(L);
3468 // State: object is at top of stack
3470 lua_getfield(L, -1, "on_rightclick");
3471 if(lua_isnil(L, -1))
3473 luaL_checktype(L, -1, LUA_TFUNCTION);
3474 lua_pushvalue(L, object); // self
3475 objectref_get_or_create(L, clicker); // Clicker reference
3476 // Call with 2 arguments, 0 results
3477 if(lua_pcall(L, 2, 0, 0))
3478 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));