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 void push_v3f(lua_State *L, v3f p)
173 lua_pushnumber(L, p.X);
174 lua_setfield(L, -2, "x");
175 lua_pushnumber(L, p.Y);
176 lua_setfield(L, -2, "y");
177 lua_pushnumber(L, p.Z);
178 lua_setfield(L, -2, "z");
181 static v2s16 read_v2s16(lua_State *L, int index)
184 luaL_checktype(L, index, LUA_TTABLE);
185 lua_getfield(L, index, "x");
186 p.X = lua_tonumber(L, -1);
188 lua_getfield(L, index, "y");
189 p.Y = lua_tonumber(L, -1);
194 static v2f read_v2f(lua_State *L, int index)
197 luaL_checktype(L, index, LUA_TTABLE);
198 lua_getfield(L, index, "x");
199 p.X = lua_tonumber(L, -1);
201 lua_getfield(L, index, "y");
202 p.Y = lua_tonumber(L, -1);
207 static v3f readFloatPos(lua_State *L, int index)
210 luaL_checktype(L, index, LUA_TTABLE);
211 lua_getfield(L, index, "x");
212 pos.X = lua_tonumber(L, -1);
214 lua_getfield(L, index, "y");
215 pos.Y = lua_tonumber(L, -1);
217 lua_getfield(L, index, "z");
218 pos.Z = lua_tonumber(L, -1);
220 pos *= BS; // Scale to internal format
224 static void pushFloatPos(lua_State *L, v3f p)
230 static void pushpos(lua_State *L, v3s16 p)
233 lua_pushnumber(L, p.X);
234 lua_setfield(L, -2, "x");
235 lua_pushnumber(L, p.Y);
236 lua_setfield(L, -2, "y");
237 lua_pushnumber(L, p.Z);
238 lua_setfield(L, -2, "z");
241 static v3s16 readpos(lua_State *L, int index)
243 // Correct rounding at <0
244 v3f pf = readFloatPos(L, index);
245 return floatToInt(pf, BS);
248 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
251 lua_pushstring(L, ndef->get(n).name.c_str());
252 lua_setfield(L, -2, "name");
253 lua_pushnumber(L, n.getParam1());
254 lua_setfield(L, -2, "param1");
255 lua_pushnumber(L, n.getParam2());
256 lua_setfield(L, -2, "param2");
259 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
261 lua_getfield(L, index, "name");
262 const char *name = luaL_checkstring(L, -1);
265 lua_getfield(L, index, "param1");
269 param1 = lua_tonumber(L, -1);
272 lua_getfield(L, index, "param2");
276 param2 = lua_tonumber(L, -1);
278 return MapNode(ndef, name, param1, param2);
281 static video::SColor readARGB8(lua_State *L, int index)
284 luaL_checktype(L, index, LUA_TTABLE);
285 lua_getfield(L, index, "a");
286 if(lua_isnumber(L, -1))
287 color.setAlpha(lua_tonumber(L, -1));
289 lua_getfield(L, index, "r");
290 color.setRed(lua_tonumber(L, -1));
292 lua_getfield(L, index, "g");
293 color.setGreen(lua_tonumber(L, -1));
295 lua_getfield(L, index, "b");
296 color.setBlue(lua_tonumber(L, -1));
301 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
303 core::aabbox3d<f32> box;
304 if(lua_istable(L, -1)){
305 lua_rawgeti(L, -1, 1);
306 box.MinEdge.X = lua_tonumber(L, -1) * scale;
308 lua_rawgeti(L, -1, 2);
309 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
311 lua_rawgeti(L, -1, 3);
312 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
314 lua_rawgeti(L, -1, 4);
315 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
317 lua_rawgeti(L, -1, 5);
318 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
320 lua_rawgeti(L, -1, 6);
321 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
327 static bool getstringfield(lua_State *L, int table,
328 const char *fieldname, std::string &result)
330 lua_getfield(L, table, fieldname);
332 if(lua_isstring(L, -1)){
333 result = lua_tostring(L, -1);
340 static bool getintfield(lua_State *L, int table,
341 const char *fieldname, int &result)
343 lua_getfield(L, table, fieldname);
345 if(lua_isnumber(L, -1)){
346 result = lua_tonumber(L, -1);
353 static bool getfloatfield(lua_State *L, int table,
354 const char *fieldname, float &result)
356 lua_getfield(L, table, fieldname);
358 if(lua_isnumber(L, -1)){
359 result = lua_tonumber(L, -1);
366 static bool getboolfield(lua_State *L, int table,
367 const char *fieldname, bool &result)
369 lua_getfield(L, table, fieldname);
371 if(lua_isboolean(L, -1)){
372 result = lua_toboolean(L, -1);
379 static std::string getstringfield_default(lua_State *L, int table,
380 const char *fieldname, const std::string &default_)
382 std::string result = default_;
383 getstringfield(L, table, fieldname, result);
387 static int getintfield_default(lua_State *L, int table,
388 const char *fieldname, int default_)
390 int result = default_;
391 getintfield(L, table, fieldname, result);
395 /*static float getfloatfield_default(lua_State *L, int table,
396 const char *fieldname, float default_)
398 float result = default_;
399 getfloatfield(L, table, fieldname, result);
403 static bool getboolfield_default(lua_State *L, int table,
404 const char *fieldname, bool default_)
406 bool result = default_;
407 getboolfield(L, table, fieldname, result);
417 static bool string_to_enum(const EnumString *spec, int &result,
418 const std::string &str)
420 const EnumString *esp = spec;
422 if(str == std::string(esp->str)){
431 /*static bool enum_to_string(const EnumString *spec, std::string &result,
434 const EnumString *esp = spec;
445 static int getenumfield(lua_State *L, int table,
446 const char *fieldname, const EnumString *spec, int default_)
448 int result = default_;
449 string_to_enum(spec, result,
450 getstringfield_default(L, table, fieldname, ""));
454 static void setfloatfield(lua_State *L, int table,
455 const char *fieldname, float value)
457 lua_pushnumber(L, value);
460 lua_setfield(L, table, fieldname);
463 static void warn_if_field_exists(lua_State *L, int table,
464 const char *fieldname, const std::string &message)
466 lua_getfield(L, table, fieldname);
467 if(!lua_isnil(L, -1)){
468 infostream<<script_get_backtrace(L)<<std::endl;
469 infostream<<"WARNING: field \""<<fieldname<<"\": "
470 <<message<<std::endl;
479 static void inventory_set_list_from_lua(Inventory *inv, const char *name,
480 lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1)
483 tableindex = lua_gettop(L) + 1 + tableindex;
484 // If nil, delete list
485 if(lua_isnil(L, tableindex)){
486 inv->deleteList(name);
489 // Otherwise set list
490 std::list<std::string> items;
491 luaL_checktype(L, tableindex, LUA_TTABLE);
492 int table = tableindex;
494 while(lua_next(L, table) != 0){
495 // key at index -2 and value at index -1
496 luaL_checktype(L, -1, LUA_TSTRING);
497 std::string itemstring = luaL_checkstring(L, -1);
498 items.push_back(itemstring);
499 // removes value, keeps key for next iteration
502 int listsize = (forcesize != -1) ? forcesize : items.size();
503 InventoryList *invlist = inv->addList(name, listsize);
505 for(std::list<std::string>::const_iterator
506 i = items.begin(); i != items.end(); i++){
507 if(forcesize != -1 && index == forcesize)
509 const std::string &itemstring = *i;
510 InventoryItem *newitem = NULL;
512 newitem = InventoryItem::deSerialize(itemstring,
514 InventoryItem *olditem = invlist->changeItem(index, newitem);
518 while(forcesize != -1 && index < forcesize){
519 InventoryItem *olditem = invlist->changeItem(index, NULL);
525 static void inventory_get_list_to_lua(Inventory *inv, const char *name,
528 InventoryList *invlist = inv->getList(name);
533 // Get the table insert function
534 lua_getglobal(L, "table");
535 lua_getfield(L, -1, "insert");
536 int table_insert = lua_gettop(L);
537 // Create and fill table
539 int table = lua_gettop(L);
540 for(u32 i=0; i<invlist->getSize(); i++){
541 InventoryItem *item = invlist->getItem(i);
542 lua_pushvalue(L, table_insert);
543 lua_pushvalue(L, table);
545 lua_pushstring(L, "");
547 lua_pushstring(L, item->getItemString().c_str());
549 if(lua_pcall(L, 2, 0, 0))
550 script_error(L, "error: %s", lua_tostring(L, -1));
555 ToolDiggingProperties
558 static ToolDiggingProperties read_tool_digging_properties(
559 lua_State *L, int table)
561 ToolDiggingProperties prop;
562 getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
563 getfloatfield(L, table, "basetime", prop.basetime);
564 getfloatfield(L, table, "dt_weight", prop.dt_weight);
565 getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
566 getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
567 getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
568 getfloatfield(L, table, "basedurability", prop.basedurability);
569 getfloatfield(L, table, "dd_weight", prop.dd_weight);
570 getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
571 getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
572 getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
576 static void set_tool_digging_properties(lua_State *L, int table,
577 const ToolDiggingProperties &prop)
579 setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
580 setfloatfield(L, table, "basetime", prop.basetime);
581 setfloatfield(L, table, "dt_weight", prop.dt_weight);
582 setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
583 setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
584 setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
585 setfloatfield(L, table, "basedurability", prop.basedurability);
586 setfloatfield(L, table, "dd_weight", prop.dd_weight);
587 setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
588 setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
589 setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
592 static void push_tool_digging_properties(lua_State *L,
593 const ToolDiggingProperties &prop)
596 set_tool_digging_properties(L, -1, prop);
603 static ToolDefinition read_tool_definition(lua_State *L, int table)
606 getstringfield(L, table, "image", def.imagename);
607 def.properties = read_tool_digging_properties(L, table);
611 static void push_tool_definition(lua_State *L, const ToolDefinition &def)
614 lua_pushstring(L, def.imagename.c_str());
615 lua_setfield(L, -2, "image");
616 set_tool_digging_properties(L, -1, def.properties);
620 EnumString definitions
623 struct EnumString es_DrawType[] =
625 {NDT_NORMAL, "normal"},
626 {NDT_AIRLIKE, "airlike"},
627 {NDT_LIQUID, "liquid"},
628 {NDT_FLOWINGLIQUID, "flowingliquid"},
629 {NDT_GLASSLIKE, "glasslike"},
630 {NDT_ALLFACES, "allfaces"},
631 {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
632 {NDT_TORCHLIKE, "torchlike"},
633 {NDT_SIGNLIKE, "signlike"},
634 {NDT_PLANTLIKE, "plantlike"},
635 {NDT_FENCELIKE, "fencelike"},
636 {NDT_RAILLIKE, "raillike"},
640 struct EnumString es_ContentParamType[] =
643 {CPT_LIGHT, "light"},
644 {CPT_MINERAL, "mineral"},
645 {CPT_FACEDIR_SIMPLE, "facedir_simple"},
649 struct EnumString es_LiquidType[] =
651 {LIQUID_NONE, "none"},
652 {LIQUID_FLOWING, "flowing"},
653 {LIQUID_SOURCE, "source"},
657 struct EnumString es_NodeBoxType[] =
659 {NODEBOX_REGULAR, "regular"},
660 {NODEBOX_FIXED, "fixed"},
661 {NODEBOX_WALLMOUNTED, "wallmounted"},
665 struct EnumString es_Diggability[] =
667 {DIGGABLE_NOT, "not"},
668 {DIGGABLE_NORMAL, "normal"},
669 {DIGGABLE_CONSTANT, "constant"},
677 static int l_register_nodedef_defaults(lua_State *L)
679 luaL_checktype(L, 1, LUA_TTABLE);
681 lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
682 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
687 // Register new object prototype
688 // register_entity(name, prototype)
689 static int l_register_entity(lua_State *L)
691 std::string name = luaL_checkstring(L, 1);
692 check_modname_prefix(L, name);
693 //infostream<<"register_entity: "<<name<<std::endl;
694 luaL_checktype(L, 2, LUA_TTABLE);
696 // Get minetest.registered_entities
697 lua_getglobal(L, "minetest");
698 lua_getfield(L, -1, "registered_entities");
699 luaL_checktype(L, -1, LUA_TTABLE);
700 int registered_entities = lua_gettop(L);
701 lua_pushvalue(L, 2); // Object = param 2 -> stack top
702 // registered_entities[name] = object
703 lua_setfield(L, registered_entities, name.c_str());
705 // Get registered object to top of stack
708 // Set __index to point to itself
709 lua_pushvalue(L, -1);
710 lua_setfield(L, -2, "__index");
712 // Set metatable.__index = metatable
713 luaL_getmetatable(L, "minetest.entity");
714 lua_pushvalue(L, -1); // duplicate metatable
715 lua_setfield(L, -2, "__index");
716 // Set object metatable
717 lua_setmetatable(L, -2);
719 return 0; /* number of results */
722 class LuaABM : public ActiveBlockModifier
728 std::set<std::string> m_trigger_contents;
729 std::set<std::string> m_required_neighbors;
730 float m_trigger_interval;
731 u32 m_trigger_chance;
733 LuaABM(lua_State *L, int id,
734 const std::set<std::string> &trigger_contents,
735 const std::set<std::string> &required_neighbors,
736 float trigger_interval, u32 trigger_chance):
739 m_trigger_contents(trigger_contents),
740 m_required_neighbors(required_neighbors),
741 m_trigger_interval(trigger_interval),
742 m_trigger_chance(trigger_chance)
745 virtual std::set<std::string> getTriggerContents()
747 return m_trigger_contents;
749 virtual std::set<std::string> getRequiredNeighbors()
751 return m_required_neighbors;
753 virtual float getTriggerInterval()
755 return m_trigger_interval;
757 virtual u32 getTriggerChance()
759 return m_trigger_chance;
761 virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
762 u32 active_object_count, u32 active_object_count_wider)
764 lua_State *L = m_lua;
767 assert(lua_checkstack(L, 20));
768 StackUnroller stack_unroller(L);
770 // Get minetest.registered_abms
771 lua_getglobal(L, "minetest");
772 lua_getfield(L, -1, "registered_abms");
773 luaL_checktype(L, -1, LUA_TTABLE);
774 int registered_abms = lua_gettop(L);
776 // Get minetest.registered_abms[m_id]
777 lua_pushnumber(L, m_id);
778 lua_gettable(L, registered_abms);
783 luaL_checktype(L, -1, LUA_TTABLE);
784 lua_getfield(L, -1, "action");
785 luaL_checktype(L, -1, LUA_TFUNCTION);
787 pushnode(L, n, env->getGameDef()->ndef());
788 lua_pushnumber(L, active_object_count);
789 lua_pushnumber(L, active_object_count_wider);
790 if(lua_pcall(L, 4, 0, 0))
791 script_error(L, "error: %s", lua_tostring(L, -1));
795 // register_abm({...})
796 static int l_register_abm(lua_State *L)
798 //infostream<<"register_abm"<<std::endl;
799 luaL_checktype(L, 1, LUA_TTABLE);
801 // Get minetest.registered_abms
802 lua_getglobal(L, "minetest");
803 lua_getfield(L, -1, "registered_abms");
804 luaL_checktype(L, -1, LUA_TTABLE);
805 int registered_abms = lua_gettop(L);
810 lua_pushnumber(L, id);
811 lua_gettable(L, registered_abms);
819 infostream<<"register_abm: id="<<id<<std::endl;
821 // registered_abms[id] = spec
822 lua_pushnumber(L, id);
824 lua_settable(L, registered_abms);
826 return 0; /* number of results */
829 // register_tool(name, {lots of stuff})
830 static int l_register_tool(lua_State *L)
832 std::string name = luaL_checkstring(L, 1);
833 check_modname_prefix(L, name);
834 //infostream<<"register_tool: "<<name<<std::endl;
835 luaL_checktype(L, 2, LUA_TTABLE);
838 // Get server from registry
839 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
840 Server *server = (Server*)lua_touserdata(L, -1);
841 // And get the writable tool definition manager from the server
842 IWritableToolDefManager *tooldef =
843 server->getWritableToolDefManager();
845 ToolDefinition def = read_tool_definition(L, table);
847 tooldef->registerTool(name, def);
848 return 0; /* number of results */
851 // register_craftitem(name, {lots of stuff})
852 static int l_register_craftitem(lua_State *L)
854 std::string name = luaL_checkstring(L, 1);
855 check_modname_prefix(L, name);
856 //infostream<<"register_craftitem: "<<name<<std::endl;
857 luaL_checktype(L, 2, LUA_TTABLE);
860 // Get server from registry
861 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
862 Server *server = (Server*)lua_touserdata(L, -1);
863 // And get the writable CraftItem definition manager from the server
864 IWritableCraftItemDefManager *craftitemdef =
865 server->getWritableCraftItemDefManager();
867 // Check if on_drop is defined
868 lua_getfield(L, table, "on_drop");
869 bool got_on_drop = !lua_isnil(L, -1);
872 // Check if on_use is defined
873 lua_getfield(L, table, "on_use");
874 bool got_on_use = !lua_isnil(L, -1);
877 CraftItemDefinition def;
879 getstringfield(L, table, "image", def.imagename);
880 getstringfield(L, table, "cookresult_itemstring", def.cookresult_item);
881 getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
882 getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
883 def.usable = getboolfield_default(L, table, "usable", got_on_use);
884 getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
885 def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
886 def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
888 // If an on_drop callback is defined, force dropcount to 1
893 craftitemdef->registerCraftItem(name, def);
895 lua_pushvalue(L, table);
896 scriptapi_add_craftitem(L, name.c_str());
898 return 0; /* number of results */
901 // register_node(name, {lots of stuff})
902 static int l_register_node(lua_State *L)
904 std::string name = luaL_checkstring(L, 1);
905 check_modname_prefix(L, name);
906 //infostream<<"register_node: "<<name<<std::endl;
907 luaL_checktype(L, 2, LUA_TTABLE);
908 int nodedef_table = 2;
910 // Get server from registry
911 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
912 Server *server = (Server*)lua_touserdata(L, -1);
913 // And get the writable node definition manager from the server
914 IWritableNodeDefManager *nodedef =
915 server->getWritableNodeDefManager();
917 // Get default node definition from registry
918 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
919 int nodedef_default = lua_gettop(L);
922 Add to minetest.registered_nodes with default as metatable
925 // Get the node definition table given as parameter
926 lua_pushvalue(L, nodedef_table);
928 // Set __index to point to itself
929 lua_pushvalue(L, -1);
930 lua_setfield(L, -2, "__index");
932 // Set nodedef_default as metatable for the definition
933 lua_pushvalue(L, nodedef_default);
934 lua_setmetatable(L, nodedef_table);
936 // minetest.registered_nodes[name] = nodedef
937 lua_getglobal(L, "minetest");
938 lua_getfield(L, -1, "registered_nodes");
939 luaL_checktype(L, -1, LUA_TTABLE);
940 lua_pushstring(L, name.c_str());
941 lua_pushvalue(L, nodedef_table);
950 // Default to getting the corresponding NodeItem when dug
951 f.dug_item = std::string("NodeItem \"")+name+"\" 1";
953 // Default to unknown_block.png as all textures
954 f.setAllTextures("unknown_block.png");
957 Read definiton from Lua
962 /* Visual definition */
964 f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
966 getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
968 lua_getfield(L, nodedef_table, "tile_images");
969 if(lua_istable(L, -1)){
970 int table = lua_gettop(L);
973 while(lua_next(L, table) != 0){
974 // key at index -2 and value at index -1
975 if(lua_isstring(L, -1))
976 f.tname_tiles[i] = lua_tostring(L, -1);
978 f.tname_tiles[i] = "";
979 // removes value, keeps key for next iteration
987 // Copy last value to all remaining textures
989 std::string lastname = f.tname_tiles[i-1];
991 f.tname_tiles[i] = lastname;
998 getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
1000 lua_getfield(L, nodedef_table, "special_materials");
1001 if(lua_istable(L, -1)){
1002 int table = lua_gettop(L);
1005 while(lua_next(L, table) != 0){
1006 // key at index -2 and value at index -1
1007 int smtable = lua_gettop(L);
1008 std::string tname = getstringfield_default(
1009 L, smtable, "image", "");
1010 bool backface_culling = getboolfield_default(
1011 L, smtable, "backface_culling", true);
1012 MaterialSpec mspec(tname, backface_culling);
1013 f.setSpecialMaterial(i, mspec);
1014 // removes value, keeps key for next iteration
1025 f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
1029 lua_getfield(L, nodedef_table, "post_effect_color");
1030 if(!lua_isnil(L, -1))
1031 f.post_effect_color = readARGB8(L, -1);
1034 f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
1035 es_ContentParamType, CPT_NONE);
1037 // True for all ground-like things like stone and mud, false for eg. trees
1038 getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
1039 f.light_propagates = (f.param_type == CPT_LIGHT);
1040 warn_if_field_exists(L, nodedef_table, "light_propagates",
1041 "deprecated: determined from paramtype");
1042 getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
1043 // This is used for collision detection.
1044 // Also for general solidness queries.
1045 getboolfield(L, nodedef_table, "walkable", f.walkable);
1046 // Player can point to these
1047 getboolfield(L, nodedef_table, "pointable", f.pointable);
1048 // Player can dig these
1049 getboolfield(L, nodedef_table, "diggable", f.diggable);
1050 // Player can climb these
1051 getboolfield(L, nodedef_table, "climbable", f.climbable);
1052 // Player can build on these
1053 getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
1054 // If true, param2 is set to direction when placed. Used for torches.
1055 // NOTE: the direction format is quite inefficient and should be changed
1056 getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
1057 // Whether this content type often contains mineral.
1058 // Used for texture atlas creation.
1059 // Currently only enabled for CONTENT_STONE.
1060 getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
1061 // Inventory item string as which the node appears in inventory when dug.
1062 // Mineral overrides this.
1063 getstringfield(L, nodedef_table, "dug_item", f.dug_item);
1064 // Extra dug item and its rarity
1065 getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
1066 // Usual get interval for extra dug item
1067 getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
1068 // Metadata name of node (eg. "furnace")
1069 getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
1070 // Whether the node is non-liquid, source liquid or flowing liquid
1071 f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
1072 es_LiquidType, LIQUID_NONE);
1073 // If the content is liquid, this is the flowing version of the liquid.
1074 getstringfield(L, nodedef_table, "liquid_alternative_flowing",
1075 f.liquid_alternative_flowing);
1076 // If the content is liquid, this is the source version of the liquid.
1077 getstringfield(L, nodedef_table, "liquid_alternative_source",
1078 f.liquid_alternative_source);
1079 // Viscosity for fluid flow, ranging from 1 to 7, with
1080 // 1 giving almost instantaneous propagation and 7 being
1081 // the slowest possible
1082 f.liquid_viscosity = getintfield_default(L, nodedef_table,
1083 "liquid_viscosity", f.liquid_viscosity);
1084 // Amount of light the node emits
1085 f.light_source = getintfield_default(L, nodedef_table,
1086 "light_source", f.light_source);
1087 f.damage_per_second = getintfield_default(L, nodedef_table,
1088 "damage_per_second", f.damage_per_second);
1090 lua_getfield(L, nodedef_table, "selection_box");
1091 if(lua_istable(L, -1)){
1092 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
1093 es_NodeBoxType, NODEBOX_REGULAR);
1095 lua_getfield(L, -1, "fixed");
1096 if(lua_istable(L, -1))
1097 f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
1100 lua_getfield(L, -1, "wall_top");
1101 if(lua_istable(L, -1))
1102 f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
1105 lua_getfield(L, -1, "wall_bottom");
1106 if(lua_istable(L, -1))
1107 f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
1110 lua_getfield(L, -1, "wall_side");
1111 if(lua_istable(L, -1))
1112 f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
1117 lua_getfield(L, nodedef_table, "material");
1118 if(lua_istable(L, -1)){
1119 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
1120 es_Diggability, DIGGABLE_NORMAL);
1122 getfloatfield(L, -1, "constant_time", f.material.constant_time);
1123 getfloatfield(L, -1, "weight", f.material.weight);
1124 getfloatfield(L, -1, "crackiness", f.material.crackiness);
1125 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
1126 getfloatfield(L, -1, "cuttability", f.material.cuttability);
1127 getfloatfield(L, -1, "flammability", f.material.flammability);
1131 getstringfield(L, nodedef_table, "cookresult_itemstring", f.cookresult_item);
1132 getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
1133 getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
1139 nodedef->set(name, f);
1141 return 0; /* number of results */
1144 // alias_node(name, convert_to_name)
1145 static int l_alias_node(lua_State *L)
1147 std::string name = luaL_checkstring(L, 1);
1148 std::string convert_to = luaL_checkstring(L, 2);
1150 // Get server from registry
1151 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1152 Server *server = (Server*)lua_touserdata(L, -1);
1153 // And get the writable node definition manager from the server
1154 IWritableNodeDefManager *nodedef =
1155 server->getWritableNodeDefManager();
1157 nodedef->setAlias(name, convert_to);
1159 return 0; /* number of results */
1162 // alias_tool(name, convert_to_name)
1163 static int l_alias_tool(lua_State *L)
1165 std::string name = luaL_checkstring(L, 1);
1166 std::string convert_to = luaL_checkstring(L, 2);
1168 // Get server from registry
1169 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1170 Server *server = (Server*)lua_touserdata(L, -1);
1171 // And get the writable tool definition manager from the server
1172 IWritableToolDefManager *tooldef =
1173 server->getWritableToolDefManager();
1175 tooldef->setAlias(name, convert_to);
1177 return 0; /* number of results */
1180 // alias_craftitem(name, convert_to_name)
1181 static int l_alias_craftitem(lua_State *L)
1183 std::string name = luaL_checkstring(L, 1);
1184 std::string convert_to = luaL_checkstring(L, 2);
1186 // Get server from registry
1187 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1188 Server *server = (Server*)lua_touserdata(L, -1);
1189 // And get the writable CraftItem definition manager from the server
1190 IWritableCraftItemDefManager *craftitemdef =
1191 server->getWritableCraftItemDefManager();
1193 craftitemdef->setAlias(name, convert_to);
1195 return 0; /* number of results */
1198 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
1199 static int l_register_craft(lua_State *L)
1201 //infostream<<"register_craft"<<std::endl;
1202 luaL_checktype(L, 1, LUA_TTABLE);
1205 // Get server from registry
1206 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1207 Server *server = (Server*)lua_touserdata(L, -1);
1208 // And get the writable craft definition manager from the server
1209 IWritableCraftDefManager *craftdef =
1210 server->getWritableCraftDefManager();
1214 std::vector<std::string> input;
1216 lua_getfield(L, table0, "output");
1217 luaL_checktype(L, -1, LUA_TSTRING);
1218 if(lua_isstring(L, -1))
1219 output = lua_tostring(L, -1);
1222 lua_getfield(L, table0, "recipe");
1223 luaL_checktype(L, -1, LUA_TTABLE);
1224 if(lua_istable(L, -1)){
1225 int table1 = lua_gettop(L);
1228 while(lua_next(L, table1) != 0){
1230 // key at index -2 and value at index -1
1231 luaL_checktype(L, -1, LUA_TTABLE);
1232 if(lua_istable(L, -1)){
1233 int table2 = lua_gettop(L);
1235 while(lua_next(L, table2) != 0){
1236 // key at index -2 and value at index -1
1237 luaL_checktype(L, -1, LUA_TSTRING);
1238 input.push_back(lua_tostring(L, -1));
1239 // removes value, keeps key for next iteration
1247 if(colcount != width){
1249 error += "Invalid crafting recipe (output=\""
1251 throw LuaError(L, error);
1254 // removes value, keeps key for next iteration
1261 CraftDefinition def(output, width, input);
1262 craftdef->registerCraft(def);
1264 return 0; /* number of results */
1267 // setting_get(name)
1268 static int l_setting_get(lua_State *L)
1270 const char *name = luaL_checkstring(L, 1);
1272 std::string value = g_settings->get(name);
1273 lua_pushstring(L, value.c_str());
1274 } catch(SettingNotFoundException &e){
1280 // setting_getbool(name)
1281 static int l_setting_getbool(lua_State *L)
1283 const char *name = luaL_checkstring(L, 1);
1285 bool value = g_settings->getBool(name);
1286 lua_pushboolean(L, value);
1287 } catch(SettingNotFoundException &e){
1293 // chat_send_all(text)
1294 static int l_chat_send_all(lua_State *L)
1296 const char *text = luaL_checkstring(L, 1);
1297 // Get server from registry
1298 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1299 Server *server = (Server*)lua_touserdata(L, -1);
1301 server->notifyPlayers(narrow_to_wide(text));
1305 // chat_send_player(name, text)
1306 static int l_chat_send_player(lua_State *L)
1308 const char *name = luaL_checkstring(L, 1);
1309 const char *text = luaL_checkstring(L, 2);
1310 // Get server from registry
1311 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1312 Server *server = (Server*)lua_touserdata(L, -1);
1314 server->notifyPlayer(name, narrow_to_wide(text));
1318 // get_player_privs(name, text)
1319 static int l_get_player_privs(lua_State *L)
1321 const char *name = luaL_checkstring(L, 1);
1322 // Get server from registry
1323 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1324 Server *server = (Server*)lua_touserdata(L, -1);
1327 int table = lua_gettop(L);
1328 u64 privs_i = server->getPlayerAuthPrivs(name);
1329 // Special case for the "name" setting (local player / server owner)
1330 if(name == g_settings->get("name"))
1332 std::set<std::string> privs_s = privsToSet(privs_i);
1333 for(std::set<std::string>::const_iterator
1334 i = privs_s.begin(); i != privs_s.end(); i++){
1335 lua_pushboolean(L, true);
1336 lua_setfield(L, table, i->c_str());
1338 lua_pushvalue(L, table);
1342 // get_modpath(modname)
1343 static int l_get_modpath(lua_State *L)
1345 const char *modname = luaL_checkstring(L, 1);
1346 // Get server from registry
1347 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1348 Server *server = (Server*)lua_touserdata(L, -1);
1350 const ModSpec *mod = server->getModSpec(modname);
1355 lua_pushstring(L, mod->path.c_str());
1359 static const struct luaL_Reg minetest_f [] = {
1360 {"register_nodedef_defaults", l_register_nodedef_defaults},
1361 {"register_entity", l_register_entity},
1362 {"register_tool", l_register_tool},
1363 {"register_craftitem", l_register_craftitem},
1364 {"register_node", l_register_node},
1365 {"register_craft", l_register_craft},
1366 {"register_abm", l_register_abm},
1367 {"alias_node", l_alias_node},
1368 {"alias_tool", l_alias_tool},
1369 {"alias_craftitem", l_alias_craftitem},
1370 {"setting_get", l_setting_get},
1371 {"setting_getbool", l_setting_getbool},
1372 {"chat_send_all", l_chat_send_all},
1373 {"chat_send_player", l_chat_send_player},
1374 {"get_player_privs", l_get_player_privs},
1375 {"get_modpath", l_get_modpath},
1383 static const struct luaL_Reg minetest_entity_m [] = {
1388 Getters for stuff in main tables
1391 static void objectref_get(lua_State *L, u16 id)
1393 // Get minetest.object_refs[i]
1394 lua_getglobal(L, "minetest");
1395 lua_getfield(L, -1, "object_refs");
1396 luaL_checktype(L, -1, LUA_TTABLE);
1397 lua_pushnumber(L, id);
1398 lua_gettable(L, -2);
1399 lua_remove(L, -2); // object_refs
1400 lua_remove(L, -2); // minetest
1403 static void luaentity_get(lua_State *L, u16 id)
1405 // Get minetest.luaentities[i]
1406 lua_getglobal(L, "minetest");
1407 lua_getfield(L, -1, "luaentities");
1408 luaL_checktype(L, -1, LUA_TTABLE);
1409 lua_pushnumber(L, id);
1410 lua_gettable(L, -2);
1411 lua_remove(L, -2); // luaentities
1412 lua_remove(L, -2); // minetest
1419 #define method(class, name) {#name, class::l_##name}
1429 ServerEnvironment *m_env;
1431 static const char className[];
1432 static const luaL_reg methods[];
1434 static NodeMetaRef *checkobject(lua_State *L, int narg)
1436 luaL_checktype(L, narg, LUA_TUSERDATA);
1437 void *ud = luaL_checkudata(L, narg, className);
1438 if(!ud) luaL_typerror(L, narg, className);
1439 return *(NodeMetaRef**)ud; // unbox pointer
1442 static NodeMetadata* getmeta(NodeMetaRef *ref)
1444 NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
1448 /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
1450 NodeMetadata *meta = getmeta(ref);
1453 if(meta->typeId() != NODEMETA_GENERIC)
1455 return (IGenericNodeMetadata*)meta;
1458 static void reportMetadataChange(NodeMetaRef *ref)
1460 // Inform other things that the metadata has changed
1461 v3s16 blockpos = getNodeBlockPos(ref->m_p);
1463 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1465 ref->m_env->getMap().dispatchEvent(&event);
1466 // Set the block to be saved
1467 MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
1469 block->raiseModified(MOD_STATE_WRITE_NEEDED,
1470 "NodeMetaRef::reportMetadataChange");
1473 // Exported functions
1475 // garbage collector
1476 static int gc_object(lua_State *L) {
1477 NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
1483 static int l_get_type(lua_State *L)
1485 NodeMetaRef *ref = checkobject(L, 1);
1486 NodeMetadata *meta = getmeta(ref);
1492 lua_pushstring(L, meta->typeName());
1496 // allows_text_input(self)
1497 static int l_allows_text_input(lua_State *L)
1499 NodeMetaRef *ref = checkobject(L, 1);
1500 NodeMetadata *meta = getmeta(ref);
1501 if(meta == NULL) return 0;
1503 lua_pushboolean(L, meta->allowsTextInput());
1507 // set_text(self, text)
1508 static int l_set_text(lua_State *L)
1510 NodeMetaRef *ref = checkobject(L, 1);
1511 NodeMetadata *meta = getmeta(ref);
1512 if(meta == NULL) return 0;
1514 std::string text = luaL_checkstring(L, 2);
1515 meta->setText(text);
1516 reportMetadataChange(ref);
1521 static int l_get_text(lua_State *L)
1523 NodeMetaRef *ref = checkobject(L, 1);
1524 NodeMetadata *meta = getmeta(ref);
1525 if(meta == NULL) return 0;
1527 std::string text = meta->getText();
1528 lua_pushstring(L, text.c_str());
1533 static int l_get_owner(lua_State *L)
1535 NodeMetaRef *ref = checkobject(L, 1);
1536 NodeMetadata *meta = getmeta(ref);
1537 if(meta == NULL) return 0;
1539 std::string owner = meta->getOwner();
1540 lua_pushstring(L, owner.c_str());
1544 /* IGenericNodeMetadata interface */
1546 // set_infotext(self, text)
1547 static int l_set_infotext(lua_State *L)
1549 infostream<<__FUNCTION_NAME<<std::endl;
1550 NodeMetaRef *ref = checkobject(L, 1);
1551 NodeMetadata *meta = getmeta(ref);
1552 if(meta == NULL) return 0;
1554 std::string text = luaL_checkstring(L, 2);
1555 meta->setInfoText(text);
1556 reportMetadataChange(ref);
1560 // inventory_set_list(self, name, {item1, item2, ...})
1561 static int l_inventory_set_list(lua_State *L)
1563 NodeMetaRef *ref = checkobject(L, 1);
1564 NodeMetadata *meta = getmeta(ref);
1565 if(meta == NULL) return 0;
1567 Inventory *inv = meta->getInventory();
1568 const char *name = luaL_checkstring(L, 2);
1569 inventory_set_list_from_lua(inv, name, L, 3,
1570 ref->m_env->getGameDef());
1571 reportMetadataChange(ref);
1575 // inventory_get_list(self, name)
1576 static int l_inventory_get_list(lua_State *L)
1578 NodeMetaRef *ref = checkobject(L, 1);
1579 NodeMetadata *meta = getmeta(ref);
1580 if(meta == NULL) return 0;
1582 Inventory *inv = meta->getInventory();
1583 const char *name = luaL_checkstring(L, 2);
1584 inventory_get_list_to_lua(inv, name, L);
1588 // set_inventory_draw_spec(self, text)
1589 static int l_set_inventory_draw_spec(lua_State *L)
1591 NodeMetaRef *ref = checkobject(L, 1);
1592 NodeMetadata *meta = getmeta(ref);
1593 if(meta == NULL) return 0;
1595 std::string text = luaL_checkstring(L, 2);
1596 meta->setInventoryDrawSpec(text);
1597 reportMetadataChange(ref);
1601 // set_allow_text_input(self, text)
1602 static int l_set_allow_text_input(lua_State *L)
1604 NodeMetaRef *ref = checkobject(L, 1);
1605 NodeMetadata *meta = getmeta(ref);
1606 if(meta == NULL) return 0;
1608 bool b = lua_toboolean(L, 2);
1609 meta->setAllowTextInput(b);
1610 reportMetadataChange(ref);
1614 // set_allow_removal(self, text)
1615 static int l_set_allow_removal(lua_State *L)
1617 NodeMetaRef *ref = checkobject(L, 1);
1618 NodeMetadata *meta = getmeta(ref);
1619 if(meta == NULL) return 0;
1621 bool b = lua_toboolean(L, 2);
1622 meta->setRemovalDisabled(!b);
1623 reportMetadataChange(ref);
1627 // set_enforce_owner(self, text)
1628 static int l_set_enforce_owner(lua_State *L)
1630 NodeMetaRef *ref = checkobject(L, 1);
1631 NodeMetadata *meta = getmeta(ref);
1632 if(meta == NULL) return 0;
1634 bool b = lua_toboolean(L, 2);
1635 meta->setEnforceOwner(b);
1636 reportMetadataChange(ref);
1640 // is_inventory_modified(self)
1641 static int l_is_inventory_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->isInventoryModified());
1651 // reset_inventory_modified(self)
1652 static int l_reset_inventory_modified(lua_State *L)
1654 NodeMetaRef *ref = checkobject(L, 1);
1655 NodeMetadata *meta = getmeta(ref);
1656 if(meta == NULL) return 0;
1658 meta->resetInventoryModified();
1659 reportMetadataChange(ref);
1663 // is_text_modified(self)
1664 static int l_is_text_modified(lua_State *L)
1666 NodeMetaRef *ref = checkobject(L, 1);
1667 NodeMetadata *meta = getmeta(ref);
1668 if(meta == NULL) return 0;
1670 lua_pushboolean(L, meta->isTextModified());
1674 // reset_text_modified(self)
1675 static int l_reset_text_modified(lua_State *L)
1677 NodeMetaRef *ref = checkobject(L, 1);
1678 NodeMetadata *meta = getmeta(ref);
1679 if(meta == NULL) return 0;
1681 meta->resetTextModified();
1682 reportMetadataChange(ref);
1686 // set_string(self, name, var)
1687 static int l_set_string(lua_State *L)
1689 NodeMetaRef *ref = checkobject(L, 1);
1690 NodeMetadata *meta = getmeta(ref);
1691 if(meta == NULL) return 0;
1693 std::string name = luaL_checkstring(L, 2);
1695 const char *s = lua_tolstring(L, 3, &len);
1696 std::string str(s, len);
1697 meta->setString(name, str);
1698 reportMetadataChange(ref);
1702 // get_string(self, name)
1703 static int l_get_string(lua_State *L)
1705 NodeMetaRef *ref = checkobject(L, 1);
1706 NodeMetadata *meta = getmeta(ref);
1707 if(meta == NULL) return 0;
1709 std::string name = luaL_checkstring(L, 2);
1710 std::string str = meta->getString(name);
1711 lua_pushlstring(L, str.c_str(), str.size());
1716 NodeMetaRef(v3s16 p, ServerEnvironment *env):
1726 // Creates an NodeMetaRef and leaves it on top of stack
1727 // Not callable from Lua; all references are created on the C side.
1728 static void create(lua_State *L, v3s16 p, ServerEnvironment *env)
1730 NodeMetaRef *o = new NodeMetaRef(p, env);
1731 //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
1732 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1733 luaL_getmetatable(L, className);
1734 lua_setmetatable(L, -2);
1737 static void Register(lua_State *L)
1740 int methodtable = lua_gettop(L);
1741 luaL_newmetatable(L, className);
1742 int metatable = lua_gettop(L);
1744 lua_pushliteral(L, "__metatable");
1745 lua_pushvalue(L, methodtable);
1746 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1748 lua_pushliteral(L, "__index");
1749 lua_pushvalue(L, methodtable);
1750 lua_settable(L, metatable);
1752 lua_pushliteral(L, "__gc");
1753 lua_pushcfunction(L, gc_object);
1754 lua_settable(L, metatable);
1756 lua_pop(L, 1); // drop metatable
1758 luaL_openlib(L, 0, methods, 0); // fill methodtable
1759 lua_pop(L, 1); // drop methodtable
1761 // Cannot be created from Lua
1762 //lua_register(L, className, create_object);
1765 const char NodeMetaRef::className[] = "NodeMetaRef";
1766 const luaL_reg NodeMetaRef::methods[] = {
1767 method(NodeMetaRef, get_type),
1768 method(NodeMetaRef, allows_text_input),
1769 method(NodeMetaRef, set_text),
1770 method(NodeMetaRef, get_text),
1771 method(NodeMetaRef, get_owner),
1772 method(NodeMetaRef, set_infotext),
1773 method(NodeMetaRef, inventory_set_list),
1774 method(NodeMetaRef, inventory_get_list),
1775 method(NodeMetaRef, set_inventory_draw_spec),
1776 method(NodeMetaRef, set_allow_text_input),
1777 method(NodeMetaRef, set_allow_removal),
1778 method(NodeMetaRef, set_enforce_owner),
1779 method(NodeMetaRef, is_inventory_modified),
1780 method(NodeMetaRef, reset_inventory_modified),
1781 method(NodeMetaRef, is_text_modified),
1782 method(NodeMetaRef, reset_text_modified),
1783 method(NodeMetaRef, set_string),
1784 method(NodeMetaRef, get_string),
1795 ServerActiveObject *m_object;
1797 static const char className[];
1798 static const luaL_reg methods[];
1800 static ObjectRef *checkobject(lua_State *L, int narg)
1802 luaL_checktype(L, narg, LUA_TUSERDATA);
1803 void *ud = luaL_checkudata(L, narg, className);
1804 if(!ud) luaL_typerror(L, narg, className);
1805 return *(ObjectRef**)ud; // unbox pointer
1808 static ServerActiveObject* getobject(ObjectRef *ref)
1810 ServerActiveObject *co = ref->m_object;
1814 static LuaEntitySAO* getluaobject(ObjectRef *ref)
1816 ServerActiveObject *obj = getobject(ref);
1819 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1821 return (LuaEntitySAO*)obj;
1824 static ServerRemotePlayer* getplayer(ObjectRef *ref)
1826 ServerActiveObject *obj = getobject(ref);
1829 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
1831 return static_cast<ServerRemotePlayer*>(obj);
1834 // Exported functions
1836 // garbage collector
1837 static int gc_object(lua_State *L) {
1838 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1839 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1845 static int l_remove(lua_State *L)
1847 ObjectRef *ref = checkobject(L, 1);
1848 ServerActiveObject *co = getobject(ref);
1849 if(co == NULL) return 0;
1850 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1851 co->m_removed = true;
1856 // returns: {x=num, y=num, z=num}
1857 static int l_getpos(lua_State *L)
1859 ObjectRef *ref = checkobject(L, 1);
1860 ServerActiveObject *co = getobject(ref);
1861 if(co == NULL) return 0;
1862 v3f pos = co->getBasePosition() / BS;
1864 lua_pushnumber(L, pos.X);
1865 lua_setfield(L, -2, "x");
1866 lua_pushnumber(L, pos.Y);
1867 lua_setfield(L, -2, "y");
1868 lua_pushnumber(L, pos.Z);
1869 lua_setfield(L, -2, "z");
1873 // setpos(self, pos)
1874 static int l_setpos(lua_State *L)
1876 ObjectRef *ref = checkobject(L, 1);
1877 //LuaEntitySAO *co = getluaobject(ref);
1878 ServerActiveObject *co = getobject(ref);
1879 if(co == NULL) return 0;
1881 v3f pos = readFloatPos(L, 2);
1887 // moveto(self, pos, continuous=false)
1888 static int l_moveto(lua_State *L)
1890 ObjectRef *ref = checkobject(L, 1);
1891 //LuaEntitySAO *co = getluaobject(ref);
1892 ServerActiveObject *co = getobject(ref);
1893 if(co == NULL) return 0;
1895 v3f pos = readFloatPos(L, 2);
1897 bool continuous = lua_toboolean(L, 3);
1899 co->moveTo(pos, continuous);
1903 // punch(self, puncher); puncher = an another ObjectRef
1904 static int l_punch(lua_State *L)
1906 ObjectRef *ref = checkobject(L, 1);
1907 ObjectRef *ref2 = checkobject(L, 2);
1908 ServerActiveObject *co = getobject(ref);
1909 ServerActiveObject *co2 = getobject(ref2);
1910 if(co == NULL) return 0;
1911 if(co2 == NULL) return 0;
1917 // right_click(self, clicker); clicker = an another ObjectRef
1918 static int l_right_click(lua_State *L)
1920 ObjectRef *ref = checkobject(L, 1);
1921 ObjectRef *ref2 = checkobject(L, 2);
1922 ServerActiveObject *co = getobject(ref);
1923 ServerActiveObject *co2 = getobject(ref2);
1924 if(co == NULL) return 0;
1925 if(co2 == NULL) return 0;
1927 co->rightClick(co2);
1931 // get_wield_digging_properties(self)
1932 static int l_get_wield_digging_properties(lua_State *L)
1934 ObjectRef *ref = checkobject(L, 1);
1935 ServerActiveObject *co = getobject(ref);
1936 if(co == NULL) return 0;
1938 ToolDiggingProperties prop;
1939 co->getWieldDiggingProperties(&prop);
1940 push_tool_digging_properties(L, prop);
1944 // damage_wielded_item(self, amount)
1945 static int l_damage_wielded_item(lua_State *L)
1947 ObjectRef *ref = checkobject(L, 1);
1948 ServerActiveObject *co = getobject(ref);
1949 if(co == NULL) return 0;
1951 int amount = lua_tonumber(L, 2);
1952 co->damageWieldedItem(amount);
1956 // add_to_inventory(self, itemstring)
1957 // returns: true if item was added, (false, "reason") otherwise
1958 static int l_add_to_inventory(lua_State *L)
1960 ObjectRef *ref = checkobject(L, 1);
1961 luaL_checkstring(L, 2);
1962 ServerActiveObject *co = getobject(ref);
1963 if(co == NULL) return 0;
1965 const char *itemstring = luaL_checkstring(L, 2);
1966 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1967 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1969 std::istringstream is(itemstring, std::ios::binary);
1970 ServerEnvironment *env = co->getEnv();
1972 IGameDef *gamedef = env->getGameDef();
1974 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1975 if(item->getCount() == 0)
1977 bool added = co->addToInventory(item);
1979 lua_pushboolean(L, added);
1981 lua_pushstring(L, "failed to add item");
1983 } catch(SerializationError &e){
1985 lua_pushboolean(L, false);
1986 lua_pushstring(L, (std::string("Invalid item: ")
1987 + e.what()).c_str());
1992 // add_to_inventory_later(self, itemstring)
1994 static int l_add_to_inventory_later(lua_State *L)
1996 ObjectRef *ref = checkobject(L, 1);
1997 luaL_checkstring(L, 2);
1998 ServerActiveObject *co = getobject(ref);
1999 if(co == NULL) return 0;
2001 const char *itemstring = luaL_checkstring(L, 2);
2002 infostream<<"ObjectRef::l_add_to_inventory_later(): id="<<co->getId()
2003 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
2005 std::istringstream is(itemstring, std::ios::binary);
2006 ServerEnvironment *env = co->getEnv();
2008 IGameDef *gamedef = env->getGameDef();
2009 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
2010 infostream<<"item="<<env<<std::endl;
2011 co->addToInventoryLater(item);
2017 // hp = number of hitpoints (2 * number of hearts)
2019 static int l_set_hp(lua_State *L)
2021 ObjectRef *ref = checkobject(L, 1);
2022 luaL_checknumber(L, 2);
2023 ServerActiveObject *co = getobject(ref);
2024 if(co == NULL) return 0;
2025 int hp = lua_tonumber(L, 2);
2026 infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
2027 <<" hp="<<hp<<std::endl;
2035 // returns: number of hitpoints (2 * number of hearts)
2036 // 0 if not applicable to this type of object
2037 static int l_get_hp(lua_State *L)
2039 ObjectRef *ref = checkobject(L, 1);
2040 ServerActiveObject *co = getobject(ref);
2041 if(co == NULL) return 0;
2042 int hp = co->getHP();
2043 infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
2044 <<" hp="<<hp<<std::endl;
2046 lua_pushnumber(L, hp);
2050 /* LuaEntitySAO-only */
2052 // setvelocity(self, {x=num, y=num, z=num})
2053 static int l_setvelocity(lua_State *L)
2055 ObjectRef *ref = checkobject(L, 1);
2056 LuaEntitySAO *co = getluaobject(ref);
2057 if(co == NULL) return 0;
2059 v3f pos = readFloatPos(L, 2);
2061 co->setVelocity(pos);
2065 // setacceleration(self, {x=num, y=num, z=num})
2066 static int l_setacceleration(lua_State *L)
2068 ObjectRef *ref = checkobject(L, 1);
2069 LuaEntitySAO *co = getluaobject(ref);
2070 if(co == NULL) return 0;
2072 v3f pos = readFloatPos(L, 2);
2074 co->setAcceleration(pos);
2078 // getacceleration(self)
2079 static int l_getacceleration(lua_State *L)
2081 ObjectRef *ref = checkobject(L, 1);
2082 LuaEntitySAO *co = getluaobject(ref);
2083 if(co == NULL) return 0;
2085 v3f v = co->getAcceleration();
2090 // settexturemod(self, mod)
2091 static int l_settexturemod(lua_State *L)
2093 ObjectRef *ref = checkobject(L, 1);
2094 LuaEntitySAO *co = getluaobject(ref);
2095 if(co == NULL) return 0;
2097 std::string mod = luaL_checkstring(L, 2);
2098 co->setTextureMod(mod);
2102 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
2103 // select_horiz_by_yawpitch=false)
2104 static int l_setsprite(lua_State *L)
2106 ObjectRef *ref = checkobject(L, 1);
2107 LuaEntitySAO *co = getluaobject(ref);
2108 if(co == NULL) return 0;
2111 if(!lua_isnil(L, 2))
2112 p = read_v2s16(L, 2);
2114 if(!lua_isnil(L, 3))
2115 num_frames = lua_tonumber(L, 3);
2116 float framelength = 0.2;
2117 if(!lua_isnil(L, 4))
2118 framelength = lua_tonumber(L, 4);
2119 bool select_horiz_by_yawpitch = false;
2120 if(!lua_isnil(L, 5))
2121 select_horiz_by_yawpitch = lua_toboolean(L, 5);
2122 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
2128 // get_player_name(self)
2129 static int l_get_player_name(lua_State *L)
2131 ObjectRef *ref = checkobject(L, 1);
2132 ServerRemotePlayer *player = getplayer(ref);
2138 lua_pushstring(L, player->getName());
2142 // inventory_set_list(self, name, {item1, item2, ...})
2143 static int l_inventory_set_list(lua_State *L)
2145 ObjectRef *ref = checkobject(L, 1);
2146 ServerRemotePlayer *player = getplayer(ref);
2147 if(player == NULL) return 0;
2148 const char *name = luaL_checkstring(L, 2);
2150 inventory_set_list_from_lua(&player->inventory, name, L, 3,
2151 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2152 player->m_inventory_not_sent = true;
2156 // inventory_get_list(self, name)
2157 static int l_inventory_get_list(lua_State *L)
2159 ObjectRef *ref = checkobject(L, 1);
2160 ServerRemotePlayer *player = getplayer(ref);
2161 if(player == NULL) return 0;
2162 const char *name = luaL_checkstring(L, 2);
2164 inventory_get_list_to_lua(&player->inventory, name, L);
2168 // get_wielded_itemstring(self)
2169 static int l_get_wielded_itemstring(lua_State *L)
2171 ObjectRef *ref = checkobject(L, 1);
2172 ServerRemotePlayer *player = getplayer(ref);
2173 if(player == NULL) return 0;
2175 InventoryItem *item = player->getWieldedItem();
2180 lua_pushstring(L, item->getItemString().c_str());
2184 // get_wielded_item(self)
2185 static int l_get_wielded_item(lua_State *L)
2187 ObjectRef *ref = checkobject(L, 1);
2188 ServerRemotePlayer *player = getplayer(ref);
2189 if(player == NULL) return 0;
2191 InventoryItem *item0 = player->getWieldedItem();
2196 if(std::string("MaterialItem") == item0->getName()){
2197 MaterialItem *item = (MaterialItem*)item0;
2199 lua_pushstring(L, "NodeItem");
2200 lua_setfield(L, -2, "type");
2201 lua_pushstring(L, item->getNodeName().c_str());
2202 lua_setfield(L, -2, "name");
2204 else if(std::string("CraftItem") == item0->getName()){
2205 CraftItem *item = (CraftItem*)item0;
2207 lua_pushstring(L, "CraftItem");
2208 lua_setfield(L, -2, "type");
2209 lua_pushstring(L, item->getSubName().c_str());
2210 lua_setfield(L, -2, "name");
2212 else if(std::string("ToolItem") == item0->getName()){
2213 ToolItem *item = (ToolItem*)item0;
2215 lua_pushstring(L, "ToolItem");
2216 lua_setfield(L, -2, "type");
2217 lua_pushstring(L, item->getToolName().c_str());
2218 lua_setfield(L, -2, "name");
2219 lua_pushstring(L, itos(item->getWear()).c_str());
2220 lua_setfield(L, -2, "wear");
2223 errorstream<<"l_get_wielded_item: Unknown item name: \""
2224 <<item0->getName()<<"\""<<std::endl;
2230 // get_look_dir(self)
2231 static int l_get_look_dir(lua_State *L)
2233 ObjectRef *ref = checkobject(L, 1);
2234 ServerRemotePlayer *player = getplayer(ref);
2235 if(player == NULL) return 0;
2237 float pitch = player->getRadPitch();
2238 float yaw = player->getRadYaw();
2239 v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
2244 // get_look_pitch(self)
2245 static int l_get_look_pitch(lua_State *L)
2247 ObjectRef *ref = checkobject(L, 1);
2248 ServerRemotePlayer *player = getplayer(ref);
2249 if(player == NULL) return 0;
2251 lua_pushnumber(L, player->getRadPitch());
2255 // get_look_yaw(self)
2256 static int l_get_look_yaw(lua_State *L)
2258 ObjectRef *ref = checkobject(L, 1);
2259 ServerRemotePlayer *player = getplayer(ref);
2260 if(player == NULL) return 0;
2262 lua_pushnumber(L, player->getRadYaw());
2267 ObjectRef(ServerActiveObject *object):
2270 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2276 infostream<<"ObjectRef destructing for id="
2277 <<m_object->getId()<<std::endl;
2279 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
2282 // Creates an ObjectRef and leaves it on top of stack
2283 // Not callable from Lua; all references are created on the C side.
2284 static void create(lua_State *L, ServerActiveObject *object)
2286 ObjectRef *o = new ObjectRef(object);
2287 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2288 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2289 luaL_getmetatable(L, className);
2290 lua_setmetatable(L, -2);
2293 static void set_null(lua_State *L)
2295 ObjectRef *o = checkobject(L, -1);
2299 static void Register(lua_State *L)
2302 int methodtable = lua_gettop(L);
2303 luaL_newmetatable(L, className);
2304 int metatable = lua_gettop(L);
2306 lua_pushliteral(L, "__metatable");
2307 lua_pushvalue(L, methodtable);
2308 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2310 lua_pushliteral(L, "__index");
2311 lua_pushvalue(L, methodtable);
2312 lua_settable(L, metatable);
2314 lua_pushliteral(L, "__gc");
2315 lua_pushcfunction(L, gc_object);
2316 lua_settable(L, metatable);
2318 lua_pop(L, 1); // drop metatable
2320 luaL_openlib(L, 0, methods, 0); // fill methodtable
2321 lua_pop(L, 1); // drop methodtable
2323 // Cannot be created from Lua
2324 //lua_register(L, className, create_object);
2327 const char ObjectRef::className[] = "ObjectRef";
2328 const luaL_reg ObjectRef::methods[] = {
2329 // ServerActiveObject
2330 method(ObjectRef, remove),
2331 method(ObjectRef, getpos),
2332 method(ObjectRef, setpos),
2333 method(ObjectRef, moveto),
2334 method(ObjectRef, punch),
2335 method(ObjectRef, right_click),
2336 method(ObjectRef, get_wield_digging_properties),
2337 method(ObjectRef, damage_wielded_item),
2338 method(ObjectRef, add_to_inventory),
2339 method(ObjectRef, add_to_inventory_later),
2340 method(ObjectRef, set_hp),
2341 method(ObjectRef, get_hp),
2342 // LuaEntitySAO-only
2343 method(ObjectRef, setvelocity),
2344 method(ObjectRef, setacceleration),
2345 method(ObjectRef, getacceleration),
2346 method(ObjectRef, settexturemod),
2347 method(ObjectRef, setsprite),
2349 method(ObjectRef, get_player_name),
2350 method(ObjectRef, inventory_set_list),
2351 method(ObjectRef, inventory_get_list),
2352 method(ObjectRef, get_wielded_itemstring),
2353 method(ObjectRef, get_wielded_item),
2354 method(ObjectRef, get_look_dir),
2355 method(ObjectRef, get_look_pitch),
2356 method(ObjectRef, get_look_yaw),
2360 // Creates a new anonymous reference if id=0
2361 static void objectref_get_or_create(lua_State *L,
2362 ServerActiveObject *cobj)
2364 if(cobj->getId() == 0){
2365 ObjectRef::create(L, cobj);
2367 objectref_get(L, cobj->getId());
2378 ServerEnvironment *m_env;
2380 static const char className[];
2381 static const luaL_reg methods[];
2383 static EnvRef *checkobject(lua_State *L, int narg)
2385 luaL_checktype(L, narg, LUA_TUSERDATA);
2386 void *ud = luaL_checkudata(L, narg, className);
2387 if(!ud) luaL_typerror(L, narg, className);
2388 return *(EnvRef**)ud; // unbox pointer
2391 // Exported functions
2393 // EnvRef:add_node(pos, node)
2394 // pos = {x=num, y=num, z=num}
2395 static int l_add_node(lua_State *L)
2397 //infostream<<"EnvRef::l_add_node()"<<std::endl;
2398 EnvRef *o = checkobject(L, 1);
2399 ServerEnvironment *env = o->m_env;
2400 if(env == NULL) return 0;
2402 v3s16 pos = readpos(L, 2);
2404 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
2406 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
2407 lua_pushboolean(L, succeeded);
2411 // EnvRef:remove_node(pos)
2412 // pos = {x=num, y=num, z=num}
2413 static int l_remove_node(lua_State *L)
2415 //infostream<<"EnvRef::l_remove_node()"<<std::endl;
2416 EnvRef *o = checkobject(L, 1);
2417 ServerEnvironment *env = o->m_env;
2418 if(env == NULL) return 0;
2420 v3s16 pos = readpos(L, 2);
2422 bool succeeded = env->getMap().removeNodeWithEvent(pos);
2423 lua_pushboolean(L, succeeded);
2427 // EnvRef:get_node(pos)
2428 // pos = {x=num, y=num, z=num}
2429 static int l_get_node(lua_State *L)
2431 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2432 EnvRef *o = checkobject(L, 1);
2433 ServerEnvironment *env = o->m_env;
2434 if(env == NULL) return 0;
2436 v3s16 pos = readpos(L, 2);
2438 MapNode n = env->getMap().getNodeNoEx(pos);
2440 pushnode(L, n, env->getGameDef()->ndef());
2444 // EnvRef:get_node_or_nil(pos)
2445 // pos = {x=num, y=num, z=num}
2446 static int l_get_node_or_nil(lua_State *L)
2448 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2449 EnvRef *o = checkobject(L, 1);
2450 ServerEnvironment *env = o->m_env;
2451 if(env == NULL) return 0;
2453 v3s16 pos = readpos(L, 2);
2456 MapNode n = env->getMap().getNode(pos);
2458 pushnode(L, n, env->getGameDef()->ndef());
2460 } catch(InvalidPositionException &e)
2467 // EnvRef:get_node_light(pos, timeofday)
2468 // pos = {x=num, y=num, z=num}
2469 // timeofday: nil = current time, 0 = night, 0.5 = day
2470 static int l_get_node_light(lua_State *L)
2472 EnvRef *o = checkobject(L, 1);
2473 ServerEnvironment *env = o->m_env;
2474 if(env == NULL) return 0;
2476 v3s16 pos = readpos(L, 2);
2477 u32 time_of_day = env->getTimeOfDay();
2478 if(lua_isnumber(L, 3))
2479 time_of_day = 24000.0 * lua_tonumber(L, 3);
2480 time_of_day %= 24000;
2481 u32 dnr = time_to_daynight_ratio(time_of_day);
2482 MapNode n = env->getMap().getNodeNoEx(pos);
2484 MapNode n = env->getMap().getNode(pos);
2485 INodeDefManager *ndef = env->getGameDef()->ndef();
2486 lua_pushinteger(L, n.getLightBlend(dnr, ndef));
2488 } catch(InvalidPositionException &e)
2495 // EnvRef:add_entity(pos, entityname)
2496 // pos = {x=num, y=num, z=num}
2497 static int l_add_entity(lua_State *L)
2499 //infostream<<"EnvRef::l_add_entity()"<<std::endl;
2500 EnvRef *o = checkobject(L, 1);
2501 ServerEnvironment *env = o->m_env;
2502 if(env == NULL) return 0;
2504 v3f pos = readFloatPos(L, 2);
2506 const char *name = luaL_checkstring(L, 3);
2508 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
2509 env->addActiveObject(obj);
2513 // EnvRef:add_item(pos, inventorystring)
2514 // pos = {x=num, y=num, z=num}
2515 static int l_add_item(lua_State *L)
2517 infostream<<"EnvRef::l_add_item()"<<std::endl;
2518 EnvRef *o = checkobject(L, 1);
2519 ServerEnvironment *env = o->m_env;
2520 if(env == NULL) return 0;
2522 v3f pos = readFloatPos(L, 2);
2524 const char *inventorystring = luaL_checkstring(L, 3);
2526 ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring);
2527 env->addActiveObject(obj);
2531 // EnvRef:add_rat(pos)
2532 // pos = {x=num, y=num, z=num}
2533 static int l_add_rat(lua_State *L)
2535 infostream<<"EnvRef::l_add_rat()"<<std::endl;
2536 EnvRef *o = checkobject(L, 1);
2537 ServerEnvironment *env = o->m_env;
2538 if(env == NULL) return 0;
2540 v3f pos = readFloatPos(L, 2);
2542 ServerActiveObject *obj = new RatSAO(env, pos);
2543 env->addActiveObject(obj);
2547 // EnvRef:add_firefly(pos)
2548 // pos = {x=num, y=num, z=num}
2549 static int l_add_firefly(lua_State *L)
2551 infostream<<"EnvRef::l_add_firefly()"<<std::endl;
2552 EnvRef *o = checkobject(L, 1);
2553 ServerEnvironment *env = o->m_env;
2554 if(env == NULL) return 0;
2556 v3f pos = readFloatPos(L, 2);
2558 ServerActiveObject *obj = new FireflySAO(env, pos);
2559 env->addActiveObject(obj);
2563 // EnvRef:get_meta(pos)
2564 static int l_get_meta(lua_State *L)
2566 //infostream<<"EnvRef::l_get_meta()"<<std::endl;
2567 EnvRef *o = checkobject(L, 1);
2568 ServerEnvironment *env = o->m_env;
2569 if(env == NULL) return 0;
2571 v3s16 p = readpos(L, 2);
2572 NodeMetaRef::create(L, p, env);
2576 // EnvRef:get_player_by_name(name)
2577 static int l_get_player_by_name(lua_State *L)
2579 EnvRef *o = checkobject(L, 1);
2580 ServerEnvironment *env = o->m_env;
2581 if(env == NULL) return 0;
2583 const char *name = luaL_checkstring(L, 2);
2584 ServerRemotePlayer *player =
2585 static_cast<ServerRemotePlayer*>(env->getPlayer(name));
2590 // Put player on stack
2591 objectref_get_or_create(L, player);
2595 // EnvRef:get_objects_inside_radius(pos, radius)
2596 static int l_get_objects_inside_radius(lua_State *L)
2598 // Get the table insert function
2599 lua_getglobal(L, "table");
2600 lua_getfield(L, -1, "insert");
2601 int table_insert = lua_gettop(L);
2603 EnvRef *o = checkobject(L, 1);
2604 ServerEnvironment *env = o->m_env;
2605 if(env == NULL) return 0;
2607 v3f pos = readFloatPos(L, 2);
2608 float radius = luaL_checknumber(L, 3) * BS;
2609 std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
2611 int table = lua_gettop(L);
2612 for(std::set<u16>::const_iterator
2613 i = ids.begin(); i != ids.end(); i++){
2614 ServerActiveObject *obj = env->getActiveObject(*i);
2615 // Insert object reference into table
2616 lua_pushvalue(L, table_insert);
2617 lua_pushvalue(L, table);
2618 objectref_get_or_create(L, obj);
2619 if(lua_pcall(L, 2, 0, 0))
2620 script_error(L, "error: %s", lua_tostring(L, -1));
2625 static int gc_object(lua_State *L) {
2626 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
2632 EnvRef(ServerEnvironment *env):
2635 infostream<<"EnvRef created"<<std::endl;
2640 infostream<<"EnvRef destructing"<<std::endl;
2643 // Creates an EnvRef and leaves it on top of stack
2644 // Not callable from Lua; all references are created on the C side.
2645 static void create(lua_State *L, ServerEnvironment *env)
2647 EnvRef *o = new EnvRef(env);
2648 //infostream<<"EnvRef::create: o="<<o<<std::endl;
2649 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2650 luaL_getmetatable(L, className);
2651 lua_setmetatable(L, -2);
2654 static void set_null(lua_State *L)
2656 EnvRef *o = checkobject(L, -1);
2660 static void Register(lua_State *L)
2663 int methodtable = lua_gettop(L);
2664 luaL_newmetatable(L, className);
2665 int metatable = lua_gettop(L);
2667 lua_pushliteral(L, "__metatable");
2668 lua_pushvalue(L, methodtable);
2669 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2671 lua_pushliteral(L, "__index");
2672 lua_pushvalue(L, methodtable);
2673 lua_settable(L, metatable);
2675 lua_pushliteral(L, "__gc");
2676 lua_pushcfunction(L, gc_object);
2677 lua_settable(L, metatable);
2679 lua_pop(L, 1); // drop metatable
2681 luaL_openlib(L, 0, methods, 0); // fill methodtable
2682 lua_pop(L, 1); // drop methodtable
2684 // Cannot be created from Lua
2685 //lua_register(L, className, create_object);
2688 const char EnvRef::className[] = "EnvRef";
2689 const luaL_reg EnvRef::methods[] = {
2690 method(EnvRef, add_node),
2691 method(EnvRef, remove_node),
2692 method(EnvRef, get_node),
2693 method(EnvRef, get_node_or_nil),
2694 method(EnvRef, get_node_light),
2695 method(EnvRef, add_entity),
2696 method(EnvRef, add_item),
2697 method(EnvRef, add_rat),
2698 method(EnvRef, add_firefly),
2699 method(EnvRef, get_meta),
2700 method(EnvRef, get_player_by_name),
2701 method(EnvRef, get_objects_inside_radius),
2706 Main export function
2709 void scriptapi_export(lua_State *L, Server *server)
2712 assert(lua_checkstack(L, 20));
2713 infostream<<"scriptapi_export"<<std::endl;
2714 StackUnroller stack_unroller(L);
2716 // Store server as light userdata in registry
2717 lua_pushlightuserdata(L, server);
2718 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
2720 // Store nil as minetest_nodedef_defaults in registry
2722 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
2724 // Register global functions in table minetest
2726 luaL_register(L, NULL, minetest_f);
2727 lua_setglobal(L, "minetest");
2729 // Get the main minetest table
2730 lua_getglobal(L, "minetest");
2732 // Add tables to minetest
2735 lua_setfield(L, -2, "registered_nodes");
2737 lua_setfield(L, -2, "registered_entities");
2739 lua_setfield(L, -2, "registered_craftitems");
2741 lua_setfield(L, -2, "registered_abms");
2744 lua_setfield(L, -2, "object_refs");
2746 lua_setfield(L, -2, "luaentities");
2748 // Create entity prototype
2749 luaL_newmetatable(L, "minetest.entity");
2750 // metatable.__index = metatable
2751 lua_pushvalue(L, -1); // Duplicate metatable
2752 lua_setfield(L, -2, "__index");
2753 // Put functions in metatable
2754 luaL_register(L, NULL, minetest_entity_m);
2755 // Put other stuff in metatable
2757 // Register reference wrappers
2758 NodeMetaRef::Register(L);
2759 EnvRef::Register(L);
2760 ObjectRef::Register(L);
2763 bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
2764 const std::string &modname)
2766 ModNameStorer modnamestorer(L, modname);
2768 if(!string_allowed(modname, "abcdefghijklmnopqrstuvwxyz"
2770 errorstream<<"Error loading mod \""<<modname
2771 <<"\": modname does not follow naming conventions: "
2772 <<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
2776 bool success = false;
2779 success = script_load(L, scriptpath.c_str());
2782 errorstream<<"Error loading mod \""<<modname
2783 <<"\": "<<e.what()<<std::endl;
2789 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
2792 assert(lua_checkstack(L, 20));
2793 infostream<<"scriptapi_add_environment"<<std::endl;
2794 StackUnroller stack_unroller(L);
2796 // Create EnvRef on stack
2797 EnvRef::create(L, env);
2798 int envref = lua_gettop(L);
2800 // minetest.env = envref
2801 lua_getglobal(L, "minetest");
2802 luaL_checktype(L, -1, LUA_TTABLE);
2803 lua_pushvalue(L, envref);
2804 lua_setfield(L, -2, "env");
2806 // Store environment as light userdata in registry
2807 lua_pushlightuserdata(L, env);
2808 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
2811 Add ActiveBlockModifiers to environment
2814 // Get minetest.registered_abms
2815 lua_getglobal(L, "minetest");
2816 lua_getfield(L, -1, "registered_abms");
2817 luaL_checktype(L, -1, LUA_TTABLE);
2818 int registered_abms = lua_gettop(L);
2820 if(lua_istable(L, registered_abms)){
2821 int table = lua_gettop(L);
2823 while(lua_next(L, table) != 0){
2824 // key at index -2 and value at index -1
2825 int id = lua_tonumber(L, -2);
2826 int current_abm = lua_gettop(L);
2828 std::set<std::string> trigger_contents;
2829 lua_getfield(L, current_abm, "nodenames");
2830 if(lua_istable(L, -1)){
2831 int table = lua_gettop(L);
2833 while(lua_next(L, table) != 0){
2834 // key at index -2 and value at index -1
2835 luaL_checktype(L, -1, LUA_TSTRING);
2836 trigger_contents.insert(lua_tostring(L, -1));
2837 // removes value, keeps key for next iteration
2840 } else if(lua_isstring(L, -1)){
2841 trigger_contents.insert(lua_tostring(L, -1));
2845 std::set<std::string> required_neighbors;
2846 lua_getfield(L, current_abm, "neighbors");
2847 if(lua_istable(L, -1)){
2848 int table = lua_gettop(L);
2850 while(lua_next(L, table) != 0){
2851 // key at index -2 and value at index -1
2852 luaL_checktype(L, -1, LUA_TSTRING);
2853 required_neighbors.insert(lua_tostring(L, -1));
2854 // removes value, keeps key for next iteration
2857 } else if(lua_isstring(L, -1)){
2858 required_neighbors.insert(lua_tostring(L, -1));
2862 float trigger_interval = 10.0;
2863 getfloatfield(L, current_abm, "interval", trigger_interval);
2865 int trigger_chance = 50;
2866 getintfield(L, current_abm, "chance", trigger_chance);
2868 LuaABM *abm = new LuaABM(L, id, trigger_contents,
2869 required_neighbors, trigger_interval, trigger_chance);
2871 env->addActiveBlockModifier(abm);
2873 // removes value, keeps key for next iteration
2881 // Dump stack top with the dump2 function
2882 static void dump2(lua_State *L, const char *name)
2884 // Dump object (debug)
2885 lua_getglobal(L, "dump2");
2886 luaL_checktype(L, -1, LUA_TFUNCTION);
2887 lua_pushvalue(L, -2); // Get previous stack top as first parameter
2888 lua_pushstring(L, name);
2889 if(lua_pcall(L, 2, 0, 0))
2890 script_error(L, "error: %s", lua_tostring(L, -1));
2898 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
2901 assert(lua_checkstack(L, 20));
2902 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
2903 StackUnroller stack_unroller(L);
2905 // Create object on stack
2906 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
2907 int object = lua_gettop(L);
2909 // Get minetest.object_refs table
2910 lua_getglobal(L, "minetest");
2911 lua_getfield(L, -1, "object_refs");
2912 luaL_checktype(L, -1, LUA_TTABLE);
2913 int objectstable = lua_gettop(L);
2915 // object_refs[id] = object
2916 lua_pushnumber(L, cobj->getId()); // Push id
2917 lua_pushvalue(L, object); // Copy object to top of stack
2918 lua_settable(L, objectstable);
2921 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
2924 assert(lua_checkstack(L, 20));
2925 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
2926 StackUnroller stack_unroller(L);
2928 // Get minetest.object_refs table
2929 lua_getglobal(L, "minetest");
2930 lua_getfield(L, -1, "object_refs");
2931 luaL_checktype(L, -1, LUA_TTABLE);
2932 int objectstable = lua_gettop(L);
2934 // Get object_refs[id]
2935 lua_pushnumber(L, cobj->getId()); // Push id
2936 lua_gettable(L, objectstable);
2937 // Set object reference to NULL
2938 ObjectRef::set_null(L);
2939 lua_pop(L, 1); // pop object
2941 // Set object_refs[id] = nil
2942 lua_pushnumber(L, cobj->getId()); // Push id
2944 lua_settable(L, objectstable);
2947 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
2948 const std::string &message)
2951 assert(lua_checkstack(L, 20));
2952 StackUnroller stack_unroller(L);
2954 // Get minetest.registered_on_chat_messages
2955 lua_getglobal(L, "minetest");
2956 lua_getfield(L, -1, "registered_on_chat_messages");
2957 luaL_checktype(L, -1, LUA_TTABLE);
2958 int table = lua_gettop(L);
2961 while(lua_next(L, table) != 0){
2962 // key at index -2 and value at index -1
2963 luaL_checktype(L, -1, LUA_TFUNCTION);
2965 lua_pushstring(L, name.c_str());
2966 lua_pushstring(L, message.c_str());
2967 if(lua_pcall(L, 2, 1, 0))
2968 script_error(L, "error: %s", lua_tostring(L, -1));
2969 bool ate = lua_toboolean(L, -1);
2973 // value removed, keep key for next iteration
2982 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
2985 assert(lua_checkstack(L, 20));
2986 StackUnroller stack_unroller(L);
2988 // Get minetest.registered_on_newplayers
2989 lua_getglobal(L, "minetest");
2990 lua_getfield(L, -1, "registered_on_newplayers");
2991 luaL_checktype(L, -1, LUA_TTABLE);
2992 int table = lua_gettop(L);
2995 while(lua_next(L, table) != 0){
2996 // key at index -2 and value at index -1
2997 luaL_checktype(L, -1, LUA_TFUNCTION);
2999 objectref_get_or_create(L, player);
3000 if(lua_pcall(L, 1, 0, 0))
3001 script_error(L, "error: %s", lua_tostring(L, -1));
3002 // value removed, keep key for next iteration
3005 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
3008 assert(lua_checkstack(L, 20));
3009 StackUnroller stack_unroller(L);
3011 bool positioning_handled_by_some = false;
3013 // Get minetest.registered_on_respawnplayers
3014 lua_getglobal(L, "minetest");
3015 lua_getfield(L, -1, "registered_on_respawnplayers");
3016 luaL_checktype(L, -1, LUA_TTABLE);
3017 int table = lua_gettop(L);
3020 while(lua_next(L, table) != 0){
3021 // key at index -2 and value at index -1
3022 luaL_checktype(L, -1, LUA_TFUNCTION);
3024 objectref_get_or_create(L, player);
3025 if(lua_pcall(L, 1, 1, 0))
3026 script_error(L, "error: %s", lua_tostring(L, -1));
3027 bool positioning_handled = lua_toboolean(L, -1);
3029 if(positioning_handled)
3030 positioning_handled_by_some = true;
3031 // value removed, keep key for next iteration
3033 return positioning_handled_by_some;
3036 void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
3038 lua_getglobal(L, "minetest");
3039 lua_getfield(L, -1, "creative_inventory");
3040 luaL_checktype(L, -1, LUA_TTABLE);
3041 inventory_set_list_from_lua(&player->inventory, "main", L, -1,
3042 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
3049 static void pushPointedThing(lua_State *L, const PointedThing& pointed)
3052 if(pointed.type == POINTEDTHING_NODE)
3054 lua_pushstring(L, "node");
3055 lua_setfield(L, -2, "type");
3056 pushpos(L, pointed.node_undersurface);
3057 lua_setfield(L, -2, "under");
3058 pushpos(L, pointed.node_abovesurface);
3059 lua_setfield(L, -2, "above");
3061 else if(pointed.type == POINTEDTHING_OBJECT)
3063 lua_pushstring(L, "object");
3064 lua_setfield(L, -2, "type");
3065 objectref_get(L, pointed.object_id);
3066 lua_setfield(L, -2, "ref");
3070 lua_pushstring(L, "nothing");
3071 lua_setfield(L, -2, "type");
3075 void scriptapi_add_craftitem(lua_State *L, const char *name)
3077 StackUnroller stack_unroller(L);
3078 assert(lua_gettop(L) > 0);
3080 // Set minetest.registered_craftitems[name] = table on top of stack
3081 lua_getglobal(L, "minetest");
3082 lua_getfield(L, -1, "registered_craftitems");
3083 luaL_checktype(L, -1, LUA_TTABLE);
3084 lua_pushvalue(L, -3); // push another reference to the table to be registered
3085 lua_setfield(L, -2, name); // set minetest.registered_craftitems[name]
3088 static bool get_craftitem_callback(lua_State *L, const char *name,
3089 const char *callbackname)
3091 // Get minetest.registered_craftitems[name][callbackname]
3092 // If that is nil or on error, return false and stack is unchanged
3093 // If that is a function, returns true and pushes the
3094 // function onto the stack
3096 lua_getglobal(L, "minetest");
3097 lua_getfield(L, -1, "registered_craftitems");
3099 luaL_checktype(L, -1, LUA_TTABLE);
3100 lua_getfield(L, -1, name);
3102 // Should be a table
3103 if(lua_type(L, -1) != LUA_TTABLE)
3105 errorstream<<"CraftItem name \""<<name<<"\" not defined"<<std::endl;
3109 lua_getfield(L, -1, callbackname);
3111 // Should be a function or nil
3112 if(lua_type(L, -1) == LUA_TFUNCTION)
3116 else if(lua_isnil(L, -1))
3123 errorstream<<"CraftItem name \""<<name<<"\" callback \""
3124 <<callbackname<<" is not a function"<<std::endl;
3130 bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
3131 ServerActiveObject *dropper, v3f pos,
3132 bool &callback_exists)
3135 assert(lua_checkstack(L, 20));
3136 //infostream<<"scriptapi_craftitem_on_drop"<<std::endl;
3137 StackUnroller stack_unroller(L);
3139 bool result = false;
3140 callback_exists = get_craftitem_callback(L, name, "on_drop");
3144 lua_pushstring(L, name);
3145 objectref_get_or_create(L, dropper);
3146 pushFloatPos(L, pos);
3147 if(lua_pcall(L, 3, 1, 0))
3148 script_error(L, "error: %s", lua_tostring(L, -1));
3149 result = lua_toboolean(L, -1);
3154 bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
3155 ServerActiveObject *placer, v3f pos,
3156 bool &callback_exists)
3159 assert(lua_checkstack(L, 20));
3160 //infostream<<"scriptapi_craftitem_on_place_on_ground"<<std::endl;
3161 StackUnroller stack_unroller(L);
3163 bool result = false;
3164 callback_exists = get_craftitem_callback(L, name, "on_place_on_ground");
3168 lua_pushstring(L, name);
3169 objectref_get_or_create(L, placer);
3170 pushFloatPos(L, pos);
3171 if(lua_pcall(L, 3, 1, 0))
3172 script_error(L, "error: %s", lua_tostring(L, -1));
3173 result = lua_toboolean(L, -1);
3178 bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
3179 ServerActiveObject *user, const PointedThing& pointed,
3180 bool &callback_exists)
3183 assert(lua_checkstack(L, 20));
3184 //infostream<<"scriptapi_craftitem_on_use"<<std::endl;
3185 StackUnroller stack_unroller(L);
3187 bool result = false;
3188 callback_exists = get_craftitem_callback(L, name, "on_use");
3192 lua_pushstring(L, name);
3193 objectref_get_or_create(L, user);
3194 pushPointedThing(L, pointed);
3195 if(lua_pcall(L, 3, 1, 0))
3196 script_error(L, "error: %s", lua_tostring(L, -1));
3197 result = lua_toboolean(L, -1);
3206 void scriptapi_environment_step(lua_State *L, float dtime)
3209 assert(lua_checkstack(L, 20));
3210 //infostream<<"scriptapi_environment_step"<<std::endl;
3211 StackUnroller stack_unroller(L);
3213 // Get minetest.registered_globalsteps
3214 lua_getglobal(L, "minetest");
3215 lua_getfield(L, -1, "registered_globalsteps");
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);
3224 lua_pushnumber(L, dtime);
3225 if(lua_pcall(L, 1, 0, 0))
3226 script_error(L, "error: %s", lua_tostring(L, -1));
3227 // value removed, keep key for next iteration
3231 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
3232 ServerActiveObject *placer)
3235 assert(lua_checkstack(L, 20));
3236 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
3237 StackUnroller stack_unroller(L);
3239 // Get server from registry
3240 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3241 Server *server = (Server*)lua_touserdata(L, -1);
3242 // And get the writable node definition manager from the server
3243 IWritableNodeDefManager *ndef =
3244 server->getWritableNodeDefManager();
3246 // Get minetest.registered_on_placenodes
3247 lua_getglobal(L, "minetest");
3248 lua_getfield(L, -1, "registered_on_placenodes");
3249 luaL_checktype(L, -1, LUA_TTABLE);
3250 int table = lua_gettop(L);
3253 while(lua_next(L, table) != 0){
3254 // key at index -2 and value at index -1
3255 luaL_checktype(L, -1, LUA_TFUNCTION);
3258 pushnode(L, newnode, ndef);
3259 objectref_get_or_create(L, placer);
3260 if(lua_pcall(L, 3, 0, 0))
3261 script_error(L, "error: %s", lua_tostring(L, -1));
3262 // value removed, keep key for next iteration
3266 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
3267 ServerActiveObject *digger)
3270 assert(lua_checkstack(L, 20));
3271 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
3272 StackUnroller stack_unroller(L);
3274 // Get server from registry
3275 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3276 Server *server = (Server*)lua_touserdata(L, -1);
3277 // And get the writable node definition manager from the server
3278 IWritableNodeDefManager *ndef =
3279 server->getWritableNodeDefManager();
3281 // Get minetest.registered_on_dignodes
3282 lua_getglobal(L, "minetest");
3283 lua_getfield(L, -1, "registered_on_dignodes");
3284 luaL_checktype(L, -1, LUA_TTABLE);
3285 int table = lua_gettop(L);
3288 while(lua_next(L, table) != 0){
3289 // key at index -2 and value at index -1
3290 luaL_checktype(L, -1, LUA_TFUNCTION);
3293 pushnode(L, oldnode, ndef);
3294 objectref_get_or_create(L, digger);
3295 if(lua_pcall(L, 3, 0, 0))
3296 script_error(L, "error: %s", lua_tostring(L, -1));
3297 // value removed, keep key for next iteration
3301 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
3302 ServerActiveObject *puncher)
3305 assert(lua_checkstack(L, 20));
3306 //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
3307 StackUnroller stack_unroller(L);
3309 // Get server from registry
3310 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
3311 Server *server = (Server*)lua_touserdata(L, -1);
3312 // And get the writable node definition manager from the server
3313 IWritableNodeDefManager *ndef =
3314 server->getWritableNodeDefManager();
3316 // Get minetest.registered_on_punchnodes
3317 lua_getglobal(L, "minetest");
3318 lua_getfield(L, -1, "registered_on_punchnodes");
3319 luaL_checktype(L, -1, LUA_TTABLE);
3320 int table = lua_gettop(L);
3323 while(lua_next(L, table) != 0){
3324 // key at index -2 and value at index -1
3325 luaL_checktype(L, -1, LUA_TFUNCTION);
3328 pushnode(L, node, ndef);
3329 objectref_get_or_create(L, puncher);
3330 if(lua_pcall(L, 3, 0, 0))
3331 script_error(L, "error: %s", lua_tostring(L, -1));
3332 // value removed, keep key for next iteration
3336 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
3339 assert(lua_checkstack(L, 20));
3340 //infostream<<"scriptapi_environment_on_generated"<<std::endl;
3341 StackUnroller stack_unroller(L);
3343 // Get minetest.registered_on_generateds
3344 lua_getglobal(L, "minetest");
3345 lua_getfield(L, -1, "registered_on_generateds");
3346 luaL_checktype(L, -1, LUA_TTABLE);
3347 int table = lua_gettop(L);
3350 while(lua_next(L, table) != 0){
3351 // key at index -2 and value at index -1
3352 luaL_checktype(L, -1, LUA_TFUNCTION);
3356 if(lua_pcall(L, 2, 0, 0))
3357 script_error(L, "error: %s", lua_tostring(L, -1));
3358 // value removed, keep key for next iteration
3366 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
3367 const std::string &staticdata)
3370 assert(lua_checkstack(L, 20));
3371 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
3372 <<name<<"\""<<std::endl;
3373 StackUnroller stack_unroller(L);
3375 // Get minetest.registered_entities[name]
3376 lua_getglobal(L, "minetest");
3377 lua_getfield(L, -1, "registered_entities");
3378 luaL_checktype(L, -1, LUA_TTABLE);
3379 lua_pushstring(L, name);
3380 lua_gettable(L, -2);
3381 // Should be a table, which we will use as a prototype
3382 //luaL_checktype(L, -1, LUA_TTABLE);
3383 if(lua_type(L, -1) != LUA_TTABLE){
3384 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
3387 int prototype_table = lua_gettop(L);
3388 //dump2(L, "prototype_table");
3390 // Create entity object
3392 int object = lua_gettop(L);
3394 // Set object metatable
3395 lua_pushvalue(L, prototype_table);
3396 lua_setmetatable(L, -2);
3398 // Add object reference
3399 // This should be userdata with metatable ObjectRef
3400 objectref_get(L, id);
3401 luaL_checktype(L, -1, LUA_TUSERDATA);
3402 if(!luaL_checkudata(L, -1, "ObjectRef"))
3403 luaL_typerror(L, -1, "ObjectRef");
3404 lua_setfield(L, -2, "object");
3406 // minetest.luaentities[id] = object
3407 lua_getglobal(L, "minetest");
3408 lua_getfield(L, -1, "luaentities");
3409 luaL_checktype(L, -1, LUA_TTABLE);
3410 lua_pushnumber(L, id); // Push id
3411 lua_pushvalue(L, object); // Copy object to top of stack
3412 lua_settable(L, -3);
3414 // Get on_activate function
3415 lua_pushvalue(L, object);
3416 lua_getfield(L, -1, "on_activate");
3417 if(!lua_isnil(L, -1)){
3418 luaL_checktype(L, -1, LUA_TFUNCTION);
3419 lua_pushvalue(L, object); // self
3420 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
3421 // Call with 2 arguments, 0 results
3422 if(lua_pcall(L, 2, 0, 0))
3423 script_error(L, "error running function %s:on_activate: %s\n",
3424 name, lua_tostring(L, -1));
3430 void scriptapi_luaentity_rm(lua_State *L, u16 id)
3433 assert(lua_checkstack(L, 20));
3434 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
3436 // Get minetest.luaentities table
3437 lua_getglobal(L, "minetest");
3438 lua_getfield(L, -1, "luaentities");
3439 luaL_checktype(L, -1, LUA_TTABLE);
3440 int objectstable = lua_gettop(L);
3442 // Set luaentities[id] = nil
3443 lua_pushnumber(L, id); // Push id
3445 lua_settable(L, objectstable);
3447 lua_pop(L, 2); // pop luaentities, minetest
3450 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
3453 assert(lua_checkstack(L, 20));
3454 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
3455 StackUnroller stack_unroller(L);
3457 // Get minetest.luaentities[id]
3458 luaentity_get(L, id);
3459 int object = lua_gettop(L);
3461 // Get get_staticdata function
3462 lua_pushvalue(L, object);
3463 lua_getfield(L, -1, "get_staticdata");
3464 if(lua_isnil(L, -1))
3467 luaL_checktype(L, -1, LUA_TFUNCTION);
3468 lua_pushvalue(L, object); // self
3469 // Call with 1 arguments, 1 results
3470 if(lua_pcall(L, 1, 1, 0))
3471 script_error(L, "error running function get_staticdata: %s\n",
3472 lua_tostring(L, -1));
3475 const char *s = lua_tolstring(L, -1, &len);
3476 return std::string(s, len);
3479 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
3480 LuaEntityProperties *prop)
3483 assert(lua_checkstack(L, 20));
3484 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
3485 StackUnroller stack_unroller(L);
3487 // Get minetest.luaentities[id]
3488 luaentity_get(L, id);
3489 //int object = lua_gettop(L);
3493 getboolfield(L, -1, "physical", prop->physical);
3495 getfloatfield(L, -1, "weight", prop->weight);
3497 lua_getfield(L, -1, "collisionbox");
3498 if(lua_istable(L, -1))
3499 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
3502 getstringfield(L, -1, "visual", prop->visual);
3504 lua_getfield(L, -1, "visual_size");
3505 if(lua_istable(L, -1))
3506 prop->visual_size = read_v2f(L, -1);
3509 lua_getfield(L, -1, "textures");
3510 if(lua_istable(L, -1)){
3511 prop->textures.clear();
3512 int table = lua_gettop(L);
3514 while(lua_next(L, table) != 0){
3515 // key at index -2 and value at index -1
3516 if(lua_isstring(L, -1))
3517 prop->textures.push_back(lua_tostring(L, -1));
3519 prop->textures.push_back("");
3520 // removes value, keeps key for next iteration
3526 lua_getfield(L, -1, "spritediv");
3527 if(lua_istable(L, -1))
3528 prop->spritediv = read_v2s16(L, -1);
3531 lua_getfield(L, -1, "initial_sprite_basepos");
3532 if(lua_istable(L, -1))
3533 prop->initial_sprite_basepos = read_v2s16(L, -1);
3537 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
3540 assert(lua_checkstack(L, 20));
3541 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3542 StackUnroller stack_unroller(L);
3544 // Get minetest.luaentities[id]
3545 luaentity_get(L, id);
3546 int object = lua_gettop(L);
3547 // State: object is at top of stack
3548 // Get step function
3549 lua_getfield(L, -1, "on_step");
3550 if(lua_isnil(L, -1))
3552 luaL_checktype(L, -1, LUA_TFUNCTION);
3553 lua_pushvalue(L, object); // self
3554 lua_pushnumber(L, dtime); // dtime
3555 // Call with 2 arguments, 0 results
3556 if(lua_pcall(L, 2, 0, 0))
3557 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
3560 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
3561 void scriptapi_luaentity_punch(lua_State *L, u16 id,
3562 ServerActiveObject *puncher, float time_from_last_punch)
3565 assert(lua_checkstack(L, 20));
3566 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3567 StackUnroller stack_unroller(L);
3569 // Get minetest.luaentities[id]
3570 luaentity_get(L, id);
3571 int object = lua_gettop(L);
3572 // State: object is at top of stack
3574 lua_getfield(L, -1, "on_punch");
3575 if(lua_isnil(L, -1))
3577 luaL_checktype(L, -1, LUA_TFUNCTION);
3578 lua_pushvalue(L, object); // self
3579 objectref_get_or_create(L, puncher); // Clicker reference
3580 lua_pushnumber(L, time_from_last_punch);
3581 // Call with 2 arguments, 0 results
3582 if(lua_pcall(L, 3, 0, 0))
3583 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
3586 // Calls entity:on_rightclick(ObjectRef clicker)
3587 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
3588 ServerActiveObject *clicker)
3591 assert(lua_checkstack(L, 20));
3592 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3593 StackUnroller stack_unroller(L);
3595 // Get minetest.luaentities[id]
3596 luaentity_get(L, id);
3597 int object = lua_gettop(L);
3598 // State: object is at top of stack
3600 lua_getfield(L, -1, "on_rightclick");
3601 if(lua_isnil(L, -1))
3603 luaL_checktype(L, -1, LUA_TFUNCTION);
3604 lua_pushvalue(L, object); // self
3605 objectref_get_or_create(L, clicker); // Clicker reference
3606 // Call with 2 arguments, 0 results
3607 if(lua_pcall(L, 2, 0, 0))
3608 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));