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 Server* get_server(lua_State *L)
209 // Get server from registry
210 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
211 return (Server*)lua_touserdata(L, -1);
214 static ServerEnvironment* get_env(lua_State *L)
216 // Get environment from registry
217 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
218 return (ServerEnvironment*)lua_touserdata(L, -1);
221 static v3f readFloatPos(lua_State *L, int index)
224 luaL_checktype(L, index, LUA_TTABLE);
225 lua_getfield(L, index, "x");
226 pos.X = lua_tonumber(L, -1);
228 lua_getfield(L, index, "y");
229 pos.Y = lua_tonumber(L, -1);
231 lua_getfield(L, index, "z");
232 pos.Z = lua_tonumber(L, -1);
234 pos *= BS; // Scale to internal format
238 static void pushFloatPos(lua_State *L, v3f p)
244 static void pushpos(lua_State *L, v3s16 p)
247 lua_pushnumber(L, p.X);
248 lua_setfield(L, -2, "x");
249 lua_pushnumber(L, p.Y);
250 lua_setfield(L, -2, "y");
251 lua_pushnumber(L, p.Z);
252 lua_setfield(L, -2, "z");
255 static v3s16 readpos(lua_State *L, int index)
257 // Correct rounding at <0
258 v3f pf = readFloatPos(L, index);
259 return floatToInt(pf, BS);
262 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
265 lua_pushstring(L, ndef->get(n).name.c_str());
266 lua_setfield(L, -2, "name");
267 lua_pushnumber(L, n.getParam1());
268 lua_setfield(L, -2, "param1");
269 lua_pushnumber(L, n.getParam2());
270 lua_setfield(L, -2, "param2");
273 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
275 lua_getfield(L, index, "name");
276 const char *name = luaL_checkstring(L, -1);
279 lua_getfield(L, index, "param1");
283 param1 = lua_tonumber(L, -1);
286 lua_getfield(L, index, "param2");
290 param2 = lua_tonumber(L, -1);
292 return MapNode(ndef, name, param1, param2);
295 static video::SColor readARGB8(lua_State *L, int index)
298 luaL_checktype(L, index, LUA_TTABLE);
299 lua_getfield(L, index, "a");
300 if(lua_isnumber(L, -1))
301 color.setAlpha(lua_tonumber(L, -1));
303 lua_getfield(L, index, "r");
304 color.setRed(lua_tonumber(L, -1));
306 lua_getfield(L, index, "g");
307 color.setGreen(lua_tonumber(L, -1));
309 lua_getfield(L, index, "b");
310 color.setBlue(lua_tonumber(L, -1));
315 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
317 core::aabbox3d<f32> box;
318 if(lua_istable(L, -1)){
319 lua_rawgeti(L, -1, 1);
320 box.MinEdge.X = lua_tonumber(L, -1) * scale;
322 lua_rawgeti(L, -1, 2);
323 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
325 lua_rawgeti(L, -1, 3);
326 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
328 lua_rawgeti(L, -1, 4);
329 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
331 lua_rawgeti(L, -1, 5);
332 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
334 lua_rawgeti(L, -1, 6);
335 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
341 static bool getstringfield(lua_State *L, int table,
342 const char *fieldname, std::string &result)
344 lua_getfield(L, table, fieldname);
346 if(lua_isstring(L, -1)){
347 result = lua_tostring(L, -1);
354 static bool getintfield(lua_State *L, int table,
355 const char *fieldname, int &result)
357 lua_getfield(L, table, fieldname);
359 if(lua_isnumber(L, -1)){
360 result = lua_tonumber(L, -1);
367 static bool getfloatfield(lua_State *L, int table,
368 const char *fieldname, float &result)
370 lua_getfield(L, table, fieldname);
372 if(lua_isnumber(L, -1)){
373 result = lua_tonumber(L, -1);
380 static bool getboolfield(lua_State *L, int table,
381 const char *fieldname, bool &result)
383 lua_getfield(L, table, fieldname);
385 if(lua_isboolean(L, -1)){
386 result = lua_toboolean(L, -1);
393 static std::string getstringfield_default(lua_State *L, int table,
394 const char *fieldname, const std::string &default_)
396 std::string result = default_;
397 getstringfield(L, table, fieldname, result);
401 static int getintfield_default(lua_State *L, int table,
402 const char *fieldname, int default_)
404 int result = default_;
405 getintfield(L, table, fieldname, result);
409 /*static float getfloatfield_default(lua_State *L, int table,
410 const char *fieldname, float default_)
412 float result = default_;
413 getfloatfield(L, table, fieldname, result);
417 static bool getboolfield_default(lua_State *L, int table,
418 const char *fieldname, bool default_)
420 bool result = default_;
421 getboolfield(L, table, fieldname, result);
431 static bool string_to_enum(const EnumString *spec, int &result,
432 const std::string &str)
434 const EnumString *esp = spec;
436 if(str == std::string(esp->str)){
445 /*static bool enum_to_string(const EnumString *spec, std::string &result,
448 const EnumString *esp = spec;
459 static int getenumfield(lua_State *L, int table,
460 const char *fieldname, const EnumString *spec, int default_)
462 int result = default_;
463 string_to_enum(spec, result,
464 getstringfield_default(L, table, fieldname, ""));
468 static void setfloatfield(lua_State *L, int table,
469 const char *fieldname, float value)
471 lua_pushnumber(L, value);
474 lua_setfield(L, table, fieldname);
477 static void warn_if_field_exists(lua_State *L, int table,
478 const char *fieldname, const std::string &message)
480 lua_getfield(L, table, fieldname);
481 if(!lua_isnil(L, -1)){
482 infostream<<script_get_backtrace(L)<<std::endl;
483 infostream<<"WARNING: field \""<<fieldname<<"\": "
484 <<message<<std::endl;
493 static void inventory_set_list_from_lua(Inventory *inv, const char *name,
494 lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1)
497 tableindex = lua_gettop(L) + 1 + tableindex;
498 // If nil, delete list
499 if(lua_isnil(L, tableindex)){
500 inv->deleteList(name);
503 // Otherwise set list
504 std::list<std::string> items;
505 luaL_checktype(L, tableindex, LUA_TTABLE);
506 int table = tableindex;
508 while(lua_next(L, table) != 0){
509 // key at index -2 and value at index -1
510 luaL_checktype(L, -1, LUA_TSTRING);
511 std::string itemstring = luaL_checkstring(L, -1);
512 items.push_back(itemstring);
513 // removes value, keeps key for next iteration
516 int listsize = (forcesize != -1) ? forcesize : items.size();
517 InventoryList *invlist = inv->addList(name, listsize);
519 for(std::list<std::string>::const_iterator
520 i = items.begin(); i != items.end(); i++){
521 if(forcesize != -1 && index == forcesize)
523 const std::string &itemstring = *i;
524 InventoryItem *newitem = NULL;
526 newitem = InventoryItem::deSerialize(itemstring,
528 InventoryItem *olditem = invlist->changeItem(index, newitem);
532 while(forcesize != -1 && index < forcesize){
533 InventoryItem *olditem = invlist->changeItem(index, NULL);
539 static void inventory_get_list_to_lua(Inventory *inv, const char *name,
542 InventoryList *invlist = inv->getList(name);
547 // Get the table insert function
548 lua_getglobal(L, "table");
549 lua_getfield(L, -1, "insert");
550 int table_insert = lua_gettop(L);
551 // Create and fill table
553 int table = lua_gettop(L);
554 for(u32 i=0; i<invlist->getSize(); i++){
555 InventoryItem *item = invlist->getItem(i);
556 lua_pushvalue(L, table_insert);
557 lua_pushvalue(L, table);
559 lua_pushstring(L, "");
561 lua_pushstring(L, item->getItemString().c_str());
563 if(lua_pcall(L, 2, 0, 0))
564 script_error(L, "error: %s", lua_tostring(L, -1));
568 static void push_stack_item(lua_State *L, InventoryItem *item0)
573 if(std::string("MaterialItem") == item0->getName()){
574 MaterialItem *item = (MaterialItem*)item0;
576 lua_pushstring(L, "NodeItem");
577 lua_setfield(L, -2, "type");
578 lua_pushstring(L, item->getNodeName().c_str());
579 lua_setfield(L, -2, "name");
581 else if(std::string("CraftItem") == item0->getName()){
582 CraftItem *item = (CraftItem*)item0;
584 lua_pushstring(L, "CraftItem");
585 lua_setfield(L, -2, "type");
586 lua_pushstring(L, item->getSubName().c_str());
587 lua_setfield(L, -2, "name");
589 else if(std::string("ToolItem") == item0->getName()){
590 ToolItem *item = (ToolItem*)item0;
592 lua_pushstring(L, "ToolItem");
593 lua_setfield(L, -2, "type");
594 lua_pushstring(L, item->getToolName().c_str());
595 lua_setfield(L, -2, "name");
596 lua_pushstring(L, itos(item->getWear()).c_str());
597 lua_setfield(L, -2, "wear");
600 errorstream<<"push_stack_item: Unknown item name: \""
601 <<item0->getName()<<"\""<<std::endl;
606 static InventoryItem* check_stack_item(lua_State *L, int index)
609 index = lua_gettop(L) + 1 + index;
610 if(lua_isnil(L, index))
612 if(!lua_istable(L, index))
613 throw LuaError(L, "check_stack_item: Item not nil or table");
614 // A very crappy implementation for now
615 // Will be replaced when unified namespace for items is made
616 std::string type = getstringfield_default(L, index, "type", "");
617 std::string name = getstringfield_default(L, index, "name", "");
618 std::string num = getstringfield_default(L, index, "wear", "_");
621 std::string itemstring = type + " \"" + name + "\" " + num;
623 return InventoryItem::deSerialize(itemstring, get_server(L));
624 }catch(SerializationError &e){
625 throw LuaError(L, std::string("check_stack_item: "
626 "internal error (itemstring=\"")+itemstring+"\")");
631 ToolDiggingProperties
634 static ToolDiggingProperties read_tool_digging_properties(
635 lua_State *L, int table)
637 ToolDiggingProperties prop;
638 getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
639 getfloatfield(L, table, "basetime", prop.basetime);
640 getfloatfield(L, table, "dt_weight", prop.dt_weight);
641 getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
642 getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
643 getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
644 getfloatfield(L, table, "basedurability", prop.basedurability);
645 getfloatfield(L, table, "dd_weight", prop.dd_weight);
646 getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
647 getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
648 getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
652 static void set_tool_digging_properties(lua_State *L, int table,
653 const ToolDiggingProperties &prop)
655 setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
656 setfloatfield(L, table, "basetime", prop.basetime);
657 setfloatfield(L, table, "dt_weight", prop.dt_weight);
658 setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
659 setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
660 setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
661 setfloatfield(L, table, "basedurability", prop.basedurability);
662 setfloatfield(L, table, "dd_weight", prop.dd_weight);
663 setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
664 setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
665 setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
668 static void push_tool_digging_properties(lua_State *L,
669 const ToolDiggingProperties &prop)
672 set_tool_digging_properties(L, -1, prop);
679 static ToolDefinition read_tool_definition(lua_State *L, int table)
682 getstringfield(L, table, "image", def.imagename);
683 def.properties = read_tool_digging_properties(L, table);
687 static void push_tool_definition(lua_State *L, const ToolDefinition &def)
690 lua_pushstring(L, def.imagename.c_str());
691 lua_setfield(L, -2, "image");
692 set_tool_digging_properties(L, -1, def.properties);
696 EnumString definitions
699 struct EnumString es_DrawType[] =
701 {NDT_NORMAL, "normal"},
702 {NDT_AIRLIKE, "airlike"},
703 {NDT_LIQUID, "liquid"},
704 {NDT_FLOWINGLIQUID, "flowingliquid"},
705 {NDT_GLASSLIKE, "glasslike"},
706 {NDT_ALLFACES, "allfaces"},
707 {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
708 {NDT_TORCHLIKE, "torchlike"},
709 {NDT_SIGNLIKE, "signlike"},
710 {NDT_PLANTLIKE, "plantlike"},
711 {NDT_FENCELIKE, "fencelike"},
712 {NDT_RAILLIKE, "raillike"},
716 struct EnumString es_ContentParamType[] =
719 {CPT_LIGHT, "light"},
720 {CPT_MINERAL, "mineral"},
721 {CPT_FACEDIR_SIMPLE, "facedir_simple"},
725 struct EnumString es_LiquidType[] =
727 {LIQUID_NONE, "none"},
728 {LIQUID_FLOWING, "flowing"},
729 {LIQUID_SOURCE, "source"},
733 struct EnumString es_NodeBoxType[] =
735 {NODEBOX_REGULAR, "regular"},
736 {NODEBOX_FIXED, "fixed"},
737 {NODEBOX_WALLMOUNTED, "wallmounted"},
741 struct EnumString es_Diggability[] =
743 {DIGGABLE_NOT, "not"},
744 {DIGGABLE_NORMAL, "normal"},
745 {DIGGABLE_CONSTANT, "constant"},
753 static int l_register_nodedef_defaults(lua_State *L)
755 luaL_checktype(L, 1, LUA_TTABLE);
757 lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
758 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
763 // Register new object prototype
764 // register_entity(name, prototype)
765 static int l_register_entity(lua_State *L)
767 std::string name = luaL_checkstring(L, 1);
768 check_modname_prefix(L, name);
769 //infostream<<"register_entity: "<<name<<std::endl;
770 luaL_checktype(L, 2, LUA_TTABLE);
772 // Get minetest.registered_entities
773 lua_getglobal(L, "minetest");
774 lua_getfield(L, -1, "registered_entities");
775 luaL_checktype(L, -1, LUA_TTABLE);
776 int registered_entities = lua_gettop(L);
777 lua_pushvalue(L, 2); // Object = param 2 -> stack top
778 // registered_entities[name] = object
779 lua_setfield(L, registered_entities, name.c_str());
781 // Get registered object to top of stack
784 // Set __index to point to itself
785 lua_pushvalue(L, -1);
786 lua_setfield(L, -2, "__index");
788 // Set metatable.__index = metatable
789 luaL_getmetatable(L, "minetest.entity");
790 lua_pushvalue(L, -1); // duplicate metatable
791 lua_setfield(L, -2, "__index");
792 // Set object metatable
793 lua_setmetatable(L, -2);
795 return 0; /* number of results */
798 class LuaABM : public ActiveBlockModifier
804 std::set<std::string> m_trigger_contents;
805 std::set<std::string> m_required_neighbors;
806 float m_trigger_interval;
807 u32 m_trigger_chance;
809 LuaABM(lua_State *L, int id,
810 const std::set<std::string> &trigger_contents,
811 const std::set<std::string> &required_neighbors,
812 float trigger_interval, u32 trigger_chance):
815 m_trigger_contents(trigger_contents),
816 m_required_neighbors(required_neighbors),
817 m_trigger_interval(trigger_interval),
818 m_trigger_chance(trigger_chance)
821 virtual std::set<std::string> getTriggerContents()
823 return m_trigger_contents;
825 virtual std::set<std::string> getRequiredNeighbors()
827 return m_required_neighbors;
829 virtual float getTriggerInterval()
831 return m_trigger_interval;
833 virtual u32 getTriggerChance()
835 return m_trigger_chance;
837 virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
838 u32 active_object_count, u32 active_object_count_wider)
840 lua_State *L = m_lua;
843 assert(lua_checkstack(L, 20));
844 StackUnroller stack_unroller(L);
846 // Get minetest.registered_abms
847 lua_getglobal(L, "minetest");
848 lua_getfield(L, -1, "registered_abms");
849 luaL_checktype(L, -1, LUA_TTABLE);
850 int registered_abms = lua_gettop(L);
852 // Get minetest.registered_abms[m_id]
853 lua_pushnumber(L, m_id);
854 lua_gettable(L, registered_abms);
859 luaL_checktype(L, -1, LUA_TTABLE);
860 lua_getfield(L, -1, "action");
861 luaL_checktype(L, -1, LUA_TFUNCTION);
863 pushnode(L, n, env->getGameDef()->ndef());
864 lua_pushnumber(L, active_object_count);
865 lua_pushnumber(L, active_object_count_wider);
866 if(lua_pcall(L, 4, 0, 0))
867 script_error(L, "error: %s", lua_tostring(L, -1));
871 // register_abm({...})
872 static int l_register_abm(lua_State *L)
874 //infostream<<"register_abm"<<std::endl;
875 luaL_checktype(L, 1, LUA_TTABLE);
877 // Get minetest.registered_abms
878 lua_getglobal(L, "minetest");
879 lua_getfield(L, -1, "registered_abms");
880 luaL_checktype(L, -1, LUA_TTABLE);
881 int registered_abms = lua_gettop(L);
886 lua_pushnumber(L, id);
887 lua_gettable(L, registered_abms);
895 infostream<<"register_abm: id="<<id<<std::endl;
897 // registered_abms[id] = spec
898 lua_pushnumber(L, id);
900 lua_settable(L, registered_abms);
902 return 0; /* number of results */
905 // register_tool(name, {lots of stuff})
906 static int l_register_tool(lua_State *L)
908 std::string name = luaL_checkstring(L, 1);
909 check_modname_prefix(L, name);
910 //infostream<<"register_tool: "<<name<<std::endl;
911 luaL_checktype(L, 2, LUA_TTABLE);
914 // Get the writable tool definition manager from the server
915 IWritableToolDefManager *tooldef =
916 get_server(L)->getWritableToolDefManager();
918 ToolDefinition def = read_tool_definition(L, table);
920 tooldef->registerTool(name, def);
921 return 0; /* number of results */
924 // register_craftitem(name, {lots of stuff})
925 static int l_register_craftitem(lua_State *L)
927 std::string name = luaL_checkstring(L, 1);
928 check_modname_prefix(L, name);
929 //infostream<<"register_craftitem: "<<name<<std::endl;
930 luaL_checktype(L, 2, LUA_TTABLE);
933 // Get the writable CraftItem definition manager from the server
934 IWritableCraftItemDefManager *craftitemdef =
935 get_server(L)->getWritableCraftItemDefManager();
937 // Check if on_drop is defined
938 lua_getfield(L, table, "on_drop");
939 bool got_on_drop = !lua_isnil(L, -1);
942 // Check if on_use is defined
943 lua_getfield(L, table, "on_use");
944 bool got_on_use = !lua_isnil(L, -1);
947 CraftItemDefinition def;
949 getstringfield(L, table, "image", def.imagename);
950 getstringfield(L, table, "cookresult_itemstring", def.cookresult_item);
951 getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
952 getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
953 def.usable = getboolfield_default(L, table, "usable", got_on_use);
954 getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
955 def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
956 def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
958 // If an on_drop callback is defined, force dropcount to 1
963 craftitemdef->registerCraftItem(name, def);
965 lua_pushvalue(L, table);
966 scriptapi_add_craftitem(L, name.c_str());
968 return 0; /* number of results */
971 // register_node(name, {lots of stuff})
972 static int l_register_node(lua_State *L)
974 std::string name = luaL_checkstring(L, 1);
975 check_modname_prefix(L, name);
976 //infostream<<"register_node: "<<name<<std::endl;
977 luaL_checktype(L, 2, LUA_TTABLE);
978 int nodedef_table = 2;
980 // Get the writable node definition manager from the server
981 IWritableNodeDefManager *nodedef =
982 get_server(L)->getWritableNodeDefManager();
984 // Get default node definition from registry
985 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
986 int nodedef_default = lua_gettop(L);
989 Add to minetest.registered_nodes with default as metatable
992 // Get the node definition table given as parameter
993 lua_pushvalue(L, nodedef_table);
995 // Set __index to point to itself
996 lua_pushvalue(L, -1);
997 lua_setfield(L, -2, "__index");
999 // Set nodedef_default as metatable for the definition
1000 lua_pushvalue(L, nodedef_default);
1001 lua_setmetatable(L, nodedef_table);
1003 // minetest.registered_nodes[name] = nodedef
1004 lua_getglobal(L, "minetest");
1005 lua_getfield(L, -1, "registered_nodes");
1006 luaL_checktype(L, -1, LUA_TTABLE);
1007 lua_pushstring(L, name.c_str());
1008 lua_pushvalue(L, nodedef_table);
1009 lua_settable(L, -3);
1017 // Default to getting the corresponding NodeItem when dug
1018 f.dug_item = std::string("NodeItem \"")+name+"\" 1";
1020 // Default to unknown_block.png as all textures
1021 f.setAllTextures("unknown_block.png");
1024 Read definiton from Lua
1029 /* Visual definition */
1031 f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
1033 getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
1035 lua_getfield(L, nodedef_table, "tile_images");
1036 if(lua_istable(L, -1)){
1037 int table = lua_gettop(L);
1040 while(lua_next(L, table) != 0){
1041 // key at index -2 and value at index -1
1042 if(lua_isstring(L, -1))
1043 f.tname_tiles[i] = lua_tostring(L, -1);
1045 f.tname_tiles[i] = "";
1046 // removes value, keeps key for next iteration
1054 // Copy last value to all remaining textures
1056 std::string lastname = f.tname_tiles[i-1];
1058 f.tname_tiles[i] = lastname;
1065 getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
1067 lua_getfield(L, nodedef_table, "special_materials");
1068 if(lua_istable(L, -1)){
1069 int table = lua_gettop(L);
1072 while(lua_next(L, table) != 0){
1073 // key at index -2 and value at index -1
1074 int smtable = lua_gettop(L);
1075 std::string tname = getstringfield_default(
1076 L, smtable, "image", "");
1077 bool backface_culling = getboolfield_default(
1078 L, smtable, "backface_culling", true);
1079 MaterialSpec mspec(tname, backface_culling);
1080 f.setSpecialMaterial(i, mspec);
1081 // removes value, keeps key for next iteration
1092 f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
1096 lua_getfield(L, nodedef_table, "post_effect_color");
1097 if(!lua_isnil(L, -1))
1098 f.post_effect_color = readARGB8(L, -1);
1101 f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
1102 es_ContentParamType, CPT_NONE);
1104 // True for all ground-like things like stone and mud, false for eg. trees
1105 getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
1106 f.light_propagates = (f.param_type == CPT_LIGHT);
1107 warn_if_field_exists(L, nodedef_table, "light_propagates",
1108 "deprecated: determined from paramtype");
1109 getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
1110 // This is used for collision detection.
1111 // Also for general solidness queries.
1112 getboolfield(L, nodedef_table, "walkable", f.walkable);
1113 // Player can point to these
1114 getboolfield(L, nodedef_table, "pointable", f.pointable);
1115 // Player can dig these
1116 getboolfield(L, nodedef_table, "diggable", f.diggable);
1117 // Player can climb these
1118 getboolfield(L, nodedef_table, "climbable", f.climbable);
1119 // Player can build on these
1120 getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
1121 // If true, param2 is set to direction when placed. Used for torches.
1122 // NOTE: the direction format is quite inefficient and should be changed
1123 getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
1124 // Whether this content type often contains mineral.
1125 // Used for texture atlas creation.
1126 // Currently only enabled for CONTENT_STONE.
1127 getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
1128 // Inventory item string as which the node appears in inventory when dug.
1129 // Mineral overrides this.
1130 getstringfield(L, nodedef_table, "dug_item", f.dug_item);
1131 // Extra dug item and its rarity
1132 getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
1133 // Usual get interval for extra dug item
1134 getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
1135 // Metadata name of node (eg. "furnace")
1136 getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
1137 // Whether the node is non-liquid, source liquid or flowing liquid
1138 f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
1139 es_LiquidType, LIQUID_NONE);
1140 // If the content is liquid, this is the flowing version of the liquid.
1141 getstringfield(L, nodedef_table, "liquid_alternative_flowing",
1142 f.liquid_alternative_flowing);
1143 // If the content is liquid, this is the source version of the liquid.
1144 getstringfield(L, nodedef_table, "liquid_alternative_source",
1145 f.liquid_alternative_source);
1146 // Viscosity for fluid flow, ranging from 1 to 7, with
1147 // 1 giving almost instantaneous propagation and 7 being
1148 // the slowest possible
1149 f.liquid_viscosity = getintfield_default(L, nodedef_table,
1150 "liquid_viscosity", f.liquid_viscosity);
1151 // Amount of light the node emits
1152 f.light_source = getintfield_default(L, nodedef_table,
1153 "light_source", f.light_source);
1154 f.damage_per_second = getintfield_default(L, nodedef_table,
1155 "damage_per_second", f.damage_per_second);
1157 lua_getfield(L, nodedef_table, "selection_box");
1158 if(lua_istable(L, -1)){
1159 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
1160 es_NodeBoxType, NODEBOX_REGULAR);
1162 lua_getfield(L, -1, "fixed");
1163 if(lua_istable(L, -1))
1164 f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
1167 lua_getfield(L, -1, "wall_top");
1168 if(lua_istable(L, -1))
1169 f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
1172 lua_getfield(L, -1, "wall_bottom");
1173 if(lua_istable(L, -1))
1174 f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
1177 lua_getfield(L, -1, "wall_side");
1178 if(lua_istable(L, -1))
1179 f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
1184 lua_getfield(L, nodedef_table, "material");
1185 if(lua_istable(L, -1)){
1186 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
1187 es_Diggability, DIGGABLE_NORMAL);
1189 getfloatfield(L, -1, "constant_time", f.material.constant_time);
1190 getfloatfield(L, -1, "weight", f.material.weight);
1191 getfloatfield(L, -1, "crackiness", f.material.crackiness);
1192 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
1193 getfloatfield(L, -1, "cuttability", f.material.cuttability);
1194 getfloatfield(L, -1, "flammability", f.material.flammability);
1198 getstringfield(L, nodedef_table, "cookresult_itemstring", f.cookresult_item);
1199 getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
1200 getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
1206 nodedef->set(name, f);
1208 return 0; /* number of results */
1211 // alias_node(name, convert_to_name)
1212 static int l_alias_node(lua_State *L)
1214 std::string name = luaL_checkstring(L, 1);
1215 std::string convert_to = luaL_checkstring(L, 2);
1217 // Get the writable node definition manager from the server
1218 IWritableNodeDefManager *nodedef =
1219 get_server(L)->getWritableNodeDefManager();
1221 nodedef->setAlias(name, convert_to);
1223 return 0; /* number of results */
1226 // alias_tool(name, convert_to_name)
1227 static int l_alias_tool(lua_State *L)
1229 std::string name = luaL_checkstring(L, 1);
1230 std::string convert_to = luaL_checkstring(L, 2);
1232 // Get the writable tool definition manager from the server
1233 IWritableToolDefManager *tooldef =
1234 get_server(L)->getWritableToolDefManager();
1236 tooldef->setAlias(name, convert_to);
1238 return 0; /* number of results */
1241 // alias_craftitem(name, convert_to_name)
1242 static int l_alias_craftitem(lua_State *L)
1244 std::string name = luaL_checkstring(L, 1);
1245 std::string convert_to = luaL_checkstring(L, 2);
1247 // Get the writable CraftItem definition manager from the server
1248 IWritableCraftItemDefManager *craftitemdef =
1249 get_server(L)->getWritableCraftItemDefManager();
1251 craftitemdef->setAlias(name, convert_to);
1253 return 0; /* number of results */
1256 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
1257 static int l_register_craft(lua_State *L)
1259 //infostream<<"register_craft"<<std::endl;
1260 luaL_checktype(L, 1, LUA_TTABLE);
1263 // Get the writable craft definition manager from the server
1264 IWritableCraftDefManager *craftdef =
1265 get_server(L)->getWritableCraftDefManager();
1269 std::vector<std::string> input;
1271 lua_getfield(L, table0, "output");
1272 luaL_checktype(L, -1, LUA_TSTRING);
1273 if(lua_isstring(L, -1))
1274 output = lua_tostring(L, -1);
1277 lua_getfield(L, table0, "recipe");
1278 luaL_checktype(L, -1, LUA_TTABLE);
1279 if(lua_istable(L, -1)){
1280 int table1 = lua_gettop(L);
1283 while(lua_next(L, table1) != 0){
1285 // key at index -2 and value at index -1
1286 luaL_checktype(L, -1, LUA_TTABLE);
1287 if(lua_istable(L, -1)){
1288 int table2 = lua_gettop(L);
1290 while(lua_next(L, table2) != 0){
1291 // key at index -2 and value at index -1
1292 luaL_checktype(L, -1, LUA_TSTRING);
1293 input.push_back(lua_tostring(L, -1));
1294 // removes value, keeps key for next iteration
1302 if(colcount != width){
1304 error += "Invalid crafting recipe (output=\""
1306 throw LuaError(L, error);
1309 // removes value, keeps key for next iteration
1316 CraftDefinition def(output, width, input);
1317 craftdef->registerCraft(def);
1319 return 0; /* number of results */
1322 // setting_get(name)
1323 static int l_setting_get(lua_State *L)
1325 const char *name = luaL_checkstring(L, 1);
1327 std::string value = g_settings->get(name);
1328 lua_pushstring(L, value.c_str());
1329 } catch(SettingNotFoundException &e){
1335 // setting_getbool(name)
1336 static int l_setting_getbool(lua_State *L)
1338 const char *name = luaL_checkstring(L, 1);
1340 bool value = g_settings->getBool(name);
1341 lua_pushboolean(L, value);
1342 } catch(SettingNotFoundException &e){
1348 // chat_send_all(text)
1349 static int l_chat_send_all(lua_State *L)
1351 const char *text = luaL_checkstring(L, 1);
1352 // Get server from registry
1353 Server *server = get_server(L);
1355 server->notifyPlayers(narrow_to_wide(text));
1359 // chat_send_player(name, text)
1360 static int l_chat_send_player(lua_State *L)
1362 const char *name = luaL_checkstring(L, 1);
1363 const char *text = luaL_checkstring(L, 2);
1364 // Get server from registry
1365 Server *server = get_server(L);
1367 server->notifyPlayer(name, narrow_to_wide(text));
1371 // get_player_privs(name, text)
1372 static int l_get_player_privs(lua_State *L)
1374 const char *name = luaL_checkstring(L, 1);
1375 // Get server from registry
1376 Server *server = get_server(L);
1379 int table = lua_gettop(L);
1380 u64 privs_i = server->getPlayerAuthPrivs(name);
1381 // Special case for the "name" setting (local player / server owner)
1382 if(name == g_settings->get("name"))
1384 std::set<std::string> privs_s = privsToSet(privs_i);
1385 for(std::set<std::string>::const_iterator
1386 i = privs_s.begin(); i != privs_s.end(); i++){
1387 lua_pushboolean(L, true);
1388 lua_setfield(L, table, i->c_str());
1390 lua_pushvalue(L, table);
1394 // get_modpath(modname)
1395 static int l_get_modpath(lua_State *L)
1397 const char *modname = luaL_checkstring(L, 1);
1398 // Get server from registry
1399 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1400 Server *server = (Server*)lua_touserdata(L, -1);
1402 const ModSpec *mod = server->getModSpec(modname);
1407 lua_pushstring(L, mod->path.c_str());
1411 static const struct luaL_Reg minetest_f [] = {
1412 {"register_nodedef_defaults", l_register_nodedef_defaults},
1413 {"register_entity", l_register_entity},
1414 {"register_tool", l_register_tool},
1415 {"register_craftitem", l_register_craftitem},
1416 {"register_node", l_register_node},
1417 {"register_craft", l_register_craft},
1418 {"register_abm", l_register_abm},
1419 {"alias_node", l_alias_node},
1420 {"alias_tool", l_alias_tool},
1421 {"alias_craftitem", l_alias_craftitem},
1422 {"setting_get", l_setting_get},
1423 {"setting_getbool", l_setting_getbool},
1424 {"chat_send_all", l_chat_send_all},
1425 {"chat_send_player", l_chat_send_player},
1426 {"get_player_privs", l_get_player_privs},
1427 {"get_modpath", l_get_modpath},
1435 static const struct luaL_Reg minetest_entity_m [] = {
1440 Getters for stuff in main tables
1443 static void objectref_get(lua_State *L, u16 id)
1445 // Get minetest.object_refs[i]
1446 lua_getglobal(L, "minetest");
1447 lua_getfield(L, -1, "object_refs");
1448 luaL_checktype(L, -1, LUA_TTABLE);
1449 lua_pushnumber(L, id);
1450 lua_gettable(L, -2);
1451 lua_remove(L, -2); // object_refs
1452 lua_remove(L, -2); // minetest
1455 static void luaentity_get(lua_State *L, u16 id)
1457 // Get minetest.luaentities[i]
1458 lua_getglobal(L, "minetest");
1459 lua_getfield(L, -1, "luaentities");
1460 luaL_checktype(L, -1, LUA_TTABLE);
1461 lua_pushnumber(L, id);
1462 lua_gettable(L, -2);
1463 lua_remove(L, -2); // luaentities
1464 lua_remove(L, -2); // minetest
1471 #define method(class, name) {#name, class::l_##name}
1480 InventoryItem *m_stack;
1482 static const char className[];
1483 static const luaL_reg methods[];
1485 // Exported functions
1487 // garbage collector
1488 static int gc_object(lua_State *L) {
1489 InvStack *o = *(InvStack **)(lua_touserdata(L, 1));
1495 static int l_take_item(lua_State *L)
1497 InvStack *o = checkobject(L, 1);
1498 push_stack_item(L, o->m_stack);
1499 if(o->m_stack->getCount() == 1){
1503 o->m_stack->remove(1);
1508 // put_item(self, item) -> true/false
1509 static int l_put_item(lua_State *L)
1511 InvStack *o = checkobject(L, 1);
1512 InventoryItem *item = check_stack_item(L, 2);
1513 if(!item){ // nil can always be inserted
1514 lua_pushboolean(L, true);
1517 if(!item->addableTo(o->m_stack)){
1518 lua_pushboolean(L, false);
1523 lua_pushboolean(L, true);
1528 InvStack(InventoryItem *item=NULL):
1538 static InvStack* checkobject(lua_State *L, int narg)
1540 luaL_checktype(L, narg, LUA_TUSERDATA);
1541 void *ud = luaL_checkudata(L, narg, className);
1542 if(!ud) luaL_typerror(L, narg, className);
1543 return *(InvStack**)ud; // unbox pointer
1546 InventoryItem* getItemCopy()
1550 return m_stack->clone();
1553 // Creates an InvStack and leaves it on top of stack
1554 static int create_object(lua_State *L)
1556 InventoryItem *item = NULL;
1557 if(lua_isstring(L, 1)){
1558 std::string itemstring = lua_tostring(L, 1);
1559 if(itemstring != ""){
1561 IGameDef *gdef = get_server(L);
1562 item = InventoryItem::deSerialize(itemstring, gdef);
1563 }catch(SerializationError &e){
1567 InvStack *o = new InvStack(item);
1568 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1569 luaL_getmetatable(L, className);
1570 lua_setmetatable(L, -2);
1573 // Not callable from Lua
1574 static int create(lua_State *L, InventoryItem *item)
1576 InvStack *o = new InvStack(item);
1577 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1578 luaL_getmetatable(L, className);
1579 lua_setmetatable(L, -2);
1583 static void Register(lua_State *L)
1586 int methodtable = lua_gettop(L);
1587 luaL_newmetatable(L, className);
1588 int metatable = lua_gettop(L);
1590 lua_pushliteral(L, "__metatable");
1591 lua_pushvalue(L, methodtable);
1592 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1594 lua_pushliteral(L, "__index");
1595 lua_pushvalue(L, methodtable);
1596 lua_settable(L, metatable);
1598 lua_pushliteral(L, "__gc");
1599 lua_pushcfunction(L, gc_object);
1600 lua_settable(L, metatable);
1602 lua_pop(L, 1); // drop metatable
1604 luaL_openlib(L, 0, methods, 0); // fill methodtable
1605 lua_pop(L, 1); // drop methodtable
1607 // Can be created from Lua (InvStack::create(itemstring))
1608 lua_register(L, className, create_object);
1611 const char InvStack::className[] = "InvStack";
1612 const luaL_reg InvStack::methods[] = {
1613 method(InvStack, take_item),
1614 method(InvStack, put_item),
1625 InventoryLocation m_loc;
1627 static const char className[];
1628 static const luaL_reg methods[];
1630 static InvRef *checkobject(lua_State *L, int narg)
1632 luaL_checktype(L, narg, LUA_TUSERDATA);
1633 void *ud = luaL_checkudata(L, narg, className);
1634 if(!ud) luaL_typerror(L, narg, className);
1635 return *(InvRef**)ud; // unbox pointer
1638 static Inventory* getinv(lua_State *L, InvRef *ref)
1640 return get_server(L)->getInventory(ref->m_loc);
1643 static InventoryList* getlist(lua_State *L, InvRef *ref,
1644 const char *listname)
1646 Inventory *inv = getinv(L, ref);
1649 return inv->getList(listname);
1652 static InventoryItem* getitem(lua_State *L, InvRef *ref,
1653 const char *listname, int i)
1655 InventoryList *list = getlist(L, ref, listname);
1658 return list->getItem(i);
1661 static void reportInventoryChange(lua_State *L, InvRef *ref)
1663 // Inform other things that the inventory has changed
1664 get_server(L)->setInventoryModified(ref->m_loc);
1667 // Exported functions
1669 // garbage collector
1670 static int gc_object(lua_State *L) {
1671 InvRef *o = *(InvRef **)(lua_touserdata(L, 1));
1676 // set_size(self, listname, size)
1677 static int l_set_size(lua_State *L)
1679 InvRef *ref = checkobject(L, 1);
1680 const char *listname = luaL_checkstring(L, 2);
1681 int newsize = luaL_checknumber(L, 3);
1682 Inventory *inv = getinv(L, ref);
1684 inv->deleteList(listname);
1687 InventoryList *list = inv->getList(listname);
1689 list->setSize(newsize);
1691 list = inv->addList(listname, newsize);
1696 // get_stack(self, listname, i)
1697 static int l_get_stack(lua_State *L)
1699 InvRef *ref = checkobject(L, 1);
1700 const char *listname = luaL_checkstring(L, 2);
1701 int i = luaL_checknumber(L, 3);
1702 InventoryItem *item = getitem(L, ref, listname, i);
1704 InvStack::create(L, NULL);
1707 InvStack::create(L, item->clone());
1711 // set_stack(self, listname, i, stack)
1712 static int l_set_stack(lua_State *L)
1714 InvRef *ref = checkobject(L, 1);
1715 const char *listname = luaL_checkstring(L, 2);
1716 int i = luaL_checknumber(L, 3);
1717 InvStack *stack = InvStack::checkobject(L, 4);
1718 InventoryList *list = getlist(L, ref, listname);
1720 lua_pushboolean(L, false);
1723 InventoryItem *newitem = stack->getItemCopy();
1724 InventoryItem *olditem = list->changeItem(i, newitem);
1725 bool success = (olditem != newitem);
1727 lua_pushboolean(L, success);
1732 InvRef(const InventoryLocation &loc):
1741 // Creates an InvRef and leaves it on top of stack
1742 // Not callable from Lua; all references are created on the C side.
1743 static void create(lua_State *L, const InventoryLocation &loc)
1745 InvRef *o = new InvRef(loc);
1746 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1747 luaL_getmetatable(L, className);
1748 lua_setmetatable(L, -2);
1750 static void createPlayer(lua_State *L, Player *player)
1752 InventoryLocation loc;
1753 loc.setPlayer(player->getName());
1756 static void createNodeMeta(lua_State *L, v3s16 p)
1758 InventoryLocation loc;
1763 static void Register(lua_State *L)
1766 int methodtable = lua_gettop(L);
1767 luaL_newmetatable(L, className);
1768 int metatable = lua_gettop(L);
1770 lua_pushliteral(L, "__metatable");
1771 lua_pushvalue(L, methodtable);
1772 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1774 lua_pushliteral(L, "__index");
1775 lua_pushvalue(L, methodtable);
1776 lua_settable(L, metatable);
1778 lua_pushliteral(L, "__gc");
1779 lua_pushcfunction(L, gc_object);
1780 lua_settable(L, metatable);
1782 lua_pop(L, 1); // drop metatable
1784 luaL_openlib(L, 0, methods, 0); // fill methodtable
1785 lua_pop(L, 1); // drop methodtable
1787 // Cannot be created from Lua
1788 //lua_register(L, className, create_object);
1791 const char InvRef::className[] = "InvRef";
1792 const luaL_reg InvRef::methods[] = {
1793 method(InvRef, set_size),
1794 method(InvRef, get_stack),
1795 method(InvRef, set_stack),
1807 ServerEnvironment *m_env;
1809 static const char className[];
1810 static const luaL_reg methods[];
1812 static NodeMetaRef *checkobject(lua_State *L, int narg)
1814 luaL_checktype(L, narg, LUA_TUSERDATA);
1815 void *ud = luaL_checkudata(L, narg, className);
1816 if(!ud) luaL_typerror(L, narg, className);
1817 return *(NodeMetaRef**)ud; // unbox pointer
1820 static NodeMetadata* getmeta(NodeMetaRef *ref)
1822 NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
1826 /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
1828 NodeMetadata *meta = getmeta(ref);
1831 if(meta->typeId() != NODEMETA_GENERIC)
1833 return (IGenericNodeMetadata*)meta;
1836 static void reportMetadataChange(NodeMetaRef *ref)
1838 // Inform other things that the metadata has changed
1839 v3s16 blockpos = getNodeBlockPos(ref->m_p);
1841 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1843 ref->m_env->getMap().dispatchEvent(&event);
1844 // Set the block to be saved
1845 MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
1847 block->raiseModified(MOD_STATE_WRITE_NEEDED,
1848 "NodeMetaRef::reportMetadataChange");
1851 // Exported functions
1853 // garbage collector
1854 static int gc_object(lua_State *L) {
1855 NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
1861 static int l_get_type(lua_State *L)
1863 NodeMetaRef *ref = checkobject(L, 1);
1864 NodeMetadata *meta = getmeta(ref);
1870 lua_pushstring(L, meta->typeName());
1874 // allows_text_input(self)
1875 static int l_allows_text_input(lua_State *L)
1877 NodeMetaRef *ref = checkobject(L, 1);
1878 NodeMetadata *meta = getmeta(ref);
1879 if(meta == NULL) return 0;
1881 lua_pushboolean(L, meta->allowsTextInput());
1885 // set_text(self, text)
1886 static int l_set_text(lua_State *L)
1888 NodeMetaRef *ref = checkobject(L, 1);
1889 NodeMetadata *meta = getmeta(ref);
1890 if(meta == NULL) return 0;
1892 std::string text = luaL_checkstring(L, 2);
1893 meta->setText(text);
1894 reportMetadataChange(ref);
1899 static int l_get_text(lua_State *L)
1901 NodeMetaRef *ref = checkobject(L, 1);
1902 NodeMetadata *meta = getmeta(ref);
1903 if(meta == NULL) return 0;
1905 std::string text = meta->getText();
1906 lua_pushstring(L, text.c_str());
1911 static int l_get_owner(lua_State *L)
1913 NodeMetaRef *ref = checkobject(L, 1);
1914 NodeMetadata *meta = getmeta(ref);
1915 if(meta == NULL) return 0;
1917 std::string owner = meta->getOwner();
1918 lua_pushstring(L, owner.c_str());
1922 /* IGenericNodeMetadata interface */
1924 // set_infotext(self, text)
1925 static int l_set_infotext(lua_State *L)
1927 infostream<<__FUNCTION_NAME<<std::endl;
1928 NodeMetaRef *ref = checkobject(L, 1);
1929 NodeMetadata *meta = getmeta(ref);
1930 if(meta == NULL) return 0;
1932 std::string text = luaL_checkstring(L, 2);
1933 meta->setInfoText(text);
1934 reportMetadataChange(ref);
1938 // inventory_set_list(self, name, {item1, item2, ...})
1939 static int l_inventory_set_list(lua_State *L)
1941 NodeMetaRef *ref = checkobject(L, 1);
1942 NodeMetadata *meta = getmeta(ref);
1943 if(meta == NULL) return 0;
1945 Inventory *inv = meta->getInventory();
1946 const char *name = luaL_checkstring(L, 2);
1947 inventory_set_list_from_lua(inv, name, L, 3,
1948 ref->m_env->getGameDef());
1949 reportMetadataChange(ref);
1953 // inventory_get_list(self, name)
1954 static int l_inventory_get_list(lua_State *L)
1956 NodeMetaRef *ref = checkobject(L, 1);
1957 NodeMetadata *meta = getmeta(ref);
1958 if(meta == NULL) return 0;
1960 Inventory *inv = meta->getInventory();
1961 const char *name = luaL_checkstring(L, 2);
1962 inventory_get_list_to_lua(inv, name, L);
1966 // set_inventory_draw_spec(self, text)
1967 static int l_set_inventory_draw_spec(lua_State *L)
1969 NodeMetaRef *ref = checkobject(L, 1);
1970 NodeMetadata *meta = getmeta(ref);
1971 if(meta == NULL) return 0;
1973 std::string text = luaL_checkstring(L, 2);
1974 meta->setInventoryDrawSpec(text);
1975 reportMetadataChange(ref);
1979 // set_allow_text_input(self, text)
1980 static int l_set_allow_text_input(lua_State *L)
1982 NodeMetaRef *ref = checkobject(L, 1);
1983 NodeMetadata *meta = getmeta(ref);
1984 if(meta == NULL) return 0;
1986 bool b = lua_toboolean(L, 2);
1987 meta->setAllowTextInput(b);
1988 reportMetadataChange(ref);
1992 // set_allow_removal(self, text)
1993 static int l_set_allow_removal(lua_State *L)
1995 NodeMetaRef *ref = checkobject(L, 1);
1996 NodeMetadata *meta = getmeta(ref);
1997 if(meta == NULL) return 0;
1999 bool b = lua_toboolean(L, 2);
2000 meta->setRemovalDisabled(!b);
2001 reportMetadataChange(ref);
2005 // set_enforce_owner(self, text)
2006 static int l_set_enforce_owner(lua_State *L)
2008 NodeMetaRef *ref = checkobject(L, 1);
2009 NodeMetadata *meta = getmeta(ref);
2010 if(meta == NULL) return 0;
2012 bool b = lua_toboolean(L, 2);
2013 meta->setEnforceOwner(b);
2014 reportMetadataChange(ref);
2018 // is_inventory_modified(self)
2019 static int l_is_inventory_modified(lua_State *L)
2021 NodeMetaRef *ref = checkobject(L, 1);
2022 NodeMetadata *meta = getmeta(ref);
2023 if(meta == NULL) return 0;
2025 lua_pushboolean(L, meta->isInventoryModified());
2029 // reset_inventory_modified(self)
2030 static int l_reset_inventory_modified(lua_State *L)
2032 NodeMetaRef *ref = checkobject(L, 1);
2033 NodeMetadata *meta = getmeta(ref);
2034 if(meta == NULL) return 0;
2036 meta->resetInventoryModified();
2037 reportMetadataChange(ref);
2041 // is_text_modified(self)
2042 static int l_is_text_modified(lua_State *L)
2044 NodeMetaRef *ref = checkobject(L, 1);
2045 NodeMetadata *meta = getmeta(ref);
2046 if(meta == NULL) return 0;
2048 lua_pushboolean(L, meta->isTextModified());
2052 // reset_text_modified(self)
2053 static int l_reset_text_modified(lua_State *L)
2055 NodeMetaRef *ref = checkobject(L, 1);
2056 NodeMetadata *meta = getmeta(ref);
2057 if(meta == NULL) return 0;
2059 meta->resetTextModified();
2060 reportMetadataChange(ref);
2064 // set_string(self, name, var)
2065 static int l_set_string(lua_State *L)
2067 NodeMetaRef *ref = checkobject(L, 1);
2068 NodeMetadata *meta = getmeta(ref);
2069 if(meta == NULL) return 0;
2071 std::string name = luaL_checkstring(L, 2);
2073 const char *s = lua_tolstring(L, 3, &len);
2074 std::string str(s, len);
2075 meta->setString(name, str);
2076 reportMetadataChange(ref);
2080 // get_string(self, name)
2081 static int l_get_string(lua_State *L)
2083 NodeMetaRef *ref = checkobject(L, 1);
2084 NodeMetadata *meta = getmeta(ref);
2085 if(meta == NULL) return 0;
2087 std::string name = luaL_checkstring(L, 2);
2088 std::string str = meta->getString(name);
2089 lua_pushlstring(L, str.c_str(), str.size());
2094 NodeMetaRef(v3s16 p, ServerEnvironment *env):
2104 // Creates an NodeMetaRef and leaves it on top of stack
2105 // Not callable from Lua; all references are created on the C side.
2106 static void create(lua_State *L, v3s16 p, ServerEnvironment *env)
2108 NodeMetaRef *o = new NodeMetaRef(p, env);
2109 //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
2110 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2111 luaL_getmetatable(L, className);
2112 lua_setmetatable(L, -2);
2115 static void Register(lua_State *L)
2118 int methodtable = lua_gettop(L);
2119 luaL_newmetatable(L, className);
2120 int metatable = lua_gettop(L);
2122 lua_pushliteral(L, "__metatable");
2123 lua_pushvalue(L, methodtable);
2124 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2126 lua_pushliteral(L, "__index");
2127 lua_pushvalue(L, methodtable);
2128 lua_settable(L, metatable);
2130 lua_pushliteral(L, "__gc");
2131 lua_pushcfunction(L, gc_object);
2132 lua_settable(L, metatable);
2134 lua_pop(L, 1); // drop metatable
2136 luaL_openlib(L, 0, methods, 0); // fill methodtable
2137 lua_pop(L, 1); // drop methodtable
2139 // Cannot be created from Lua
2140 //lua_register(L, className, create_object);
2143 const char NodeMetaRef::className[] = "NodeMetaRef";
2144 const luaL_reg NodeMetaRef::methods[] = {
2145 method(NodeMetaRef, get_type),
2146 method(NodeMetaRef, allows_text_input),
2147 method(NodeMetaRef, set_text),
2148 method(NodeMetaRef, get_text),
2149 method(NodeMetaRef, get_owner),
2150 method(NodeMetaRef, set_infotext),
2151 method(NodeMetaRef, inventory_set_list),
2152 method(NodeMetaRef, inventory_get_list),
2153 method(NodeMetaRef, set_inventory_draw_spec),
2154 method(NodeMetaRef, set_allow_text_input),
2155 method(NodeMetaRef, set_allow_removal),
2156 method(NodeMetaRef, set_enforce_owner),
2157 method(NodeMetaRef, is_inventory_modified),
2158 method(NodeMetaRef, reset_inventory_modified),
2159 method(NodeMetaRef, is_text_modified),
2160 method(NodeMetaRef, reset_text_modified),
2161 method(NodeMetaRef, set_string),
2162 method(NodeMetaRef, get_string),
2173 ServerActiveObject *m_object;
2175 static const char className[];
2176 static const luaL_reg methods[];
2178 static ObjectRef *checkobject(lua_State *L, int narg)
2180 luaL_checktype(L, narg, LUA_TUSERDATA);
2181 void *ud = luaL_checkudata(L, narg, className);
2182 if(!ud) luaL_typerror(L, narg, className);
2183 return *(ObjectRef**)ud; // unbox pointer
2186 static ServerActiveObject* getobject(ObjectRef *ref)
2188 ServerActiveObject *co = ref->m_object;
2192 static LuaEntitySAO* getluaobject(ObjectRef *ref)
2194 ServerActiveObject *obj = getobject(ref);
2197 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
2199 return (LuaEntitySAO*)obj;
2202 static ServerRemotePlayer* getplayer(ObjectRef *ref)
2204 ServerActiveObject *obj = getobject(ref);
2207 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
2209 return static_cast<ServerRemotePlayer*>(obj);
2212 // Exported functions
2214 // garbage collector
2215 static int gc_object(lua_State *L) {
2216 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
2217 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
2223 static int l_remove(lua_State *L)
2225 ObjectRef *ref = checkobject(L, 1);
2226 ServerActiveObject *co = getobject(ref);
2227 if(co == NULL) return 0;
2228 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
2229 co->m_removed = true;
2234 // returns: {x=num, y=num, z=num}
2235 static int l_getpos(lua_State *L)
2237 ObjectRef *ref = checkobject(L, 1);
2238 ServerActiveObject *co = getobject(ref);
2239 if(co == NULL) return 0;
2240 v3f pos = co->getBasePosition() / BS;
2242 lua_pushnumber(L, pos.X);
2243 lua_setfield(L, -2, "x");
2244 lua_pushnumber(L, pos.Y);
2245 lua_setfield(L, -2, "y");
2246 lua_pushnumber(L, pos.Z);
2247 lua_setfield(L, -2, "z");
2251 // setpos(self, pos)
2252 static int l_setpos(lua_State *L)
2254 ObjectRef *ref = checkobject(L, 1);
2255 //LuaEntitySAO *co = getluaobject(ref);
2256 ServerActiveObject *co = getobject(ref);
2257 if(co == NULL) return 0;
2259 v3f pos = readFloatPos(L, 2);
2265 // moveto(self, pos, continuous=false)
2266 static int l_moveto(lua_State *L)
2268 ObjectRef *ref = checkobject(L, 1);
2269 //LuaEntitySAO *co = getluaobject(ref);
2270 ServerActiveObject *co = getobject(ref);
2271 if(co == NULL) return 0;
2273 v3f pos = readFloatPos(L, 2);
2275 bool continuous = lua_toboolean(L, 3);
2277 co->moveTo(pos, continuous);
2281 // punch(self, puncher); puncher = an another ObjectRef
2282 static int l_punch(lua_State *L)
2284 ObjectRef *ref = checkobject(L, 1);
2285 ObjectRef *ref2 = checkobject(L, 2);
2286 ServerActiveObject *co = getobject(ref);
2287 ServerActiveObject *co2 = getobject(ref2);
2288 if(co == NULL) return 0;
2289 if(co2 == NULL) return 0;
2295 // right_click(self, clicker); clicker = an another ObjectRef
2296 static int l_right_click(lua_State *L)
2298 ObjectRef *ref = checkobject(L, 1);
2299 ObjectRef *ref2 = checkobject(L, 2);
2300 ServerActiveObject *co = getobject(ref);
2301 ServerActiveObject *co2 = getobject(ref2);
2302 if(co == NULL) return 0;
2303 if(co2 == NULL) return 0;
2305 co->rightClick(co2);
2309 // get_wield_digging_properties(self)
2310 static int l_get_wield_digging_properties(lua_State *L)
2312 ObjectRef *ref = checkobject(L, 1);
2313 ServerActiveObject *co = getobject(ref);
2314 if(co == NULL) return 0;
2316 ToolDiggingProperties prop;
2317 co->getWieldDiggingProperties(&prop);
2318 push_tool_digging_properties(L, prop);
2322 // damage_wielded_item(self, amount)
2323 static int l_damage_wielded_item(lua_State *L)
2325 ObjectRef *ref = checkobject(L, 1);
2326 ServerActiveObject *co = getobject(ref);
2327 if(co == NULL) return 0;
2329 int amount = lua_tonumber(L, 2);
2330 co->damageWieldedItem(amount);
2334 // add_to_inventory(self, itemstring)
2335 // returns: true if item was added, (false, "reason") otherwise
2336 static int l_add_to_inventory(lua_State *L)
2338 ObjectRef *ref = checkobject(L, 1);
2339 luaL_checkstring(L, 2);
2340 ServerActiveObject *co = getobject(ref);
2341 if(co == NULL) return 0;
2343 const char *itemstring = luaL_checkstring(L, 2);
2344 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
2345 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
2347 std::istringstream is(itemstring, std::ios::binary);
2348 ServerEnvironment *env = co->getEnv();
2350 IGameDef *gamedef = env->getGameDef();
2352 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
2353 if(item->getCount() == 0)
2355 bool added = co->addToInventory(item);
2357 lua_pushboolean(L, added);
2359 lua_pushstring(L, "failed to add item");
2361 } catch(SerializationError &e){
2363 lua_pushboolean(L, false);
2364 lua_pushstring(L, (std::string("Invalid item: ")
2365 + e.what()).c_str());
2370 // add_to_inventory_later(self, itemstring)
2372 static int l_add_to_inventory_later(lua_State *L)
2374 ObjectRef *ref = checkobject(L, 1);
2375 luaL_checkstring(L, 2);
2376 ServerActiveObject *co = getobject(ref);
2377 if(co == NULL) return 0;
2379 const char *itemstring = luaL_checkstring(L, 2);
2380 infostream<<"ObjectRef::l_add_to_inventory_later(): id="<<co->getId()
2381 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
2383 std::istringstream is(itemstring, std::ios::binary);
2384 ServerEnvironment *env = co->getEnv();
2386 IGameDef *gamedef = env->getGameDef();
2387 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
2388 infostream<<"item="<<env<<std::endl;
2389 co->addToInventoryLater(item);
2395 // hp = number of hitpoints (2 * number of hearts)
2397 static int l_set_hp(lua_State *L)
2399 ObjectRef *ref = checkobject(L, 1);
2400 luaL_checknumber(L, 2);
2401 ServerActiveObject *co = getobject(ref);
2402 if(co == NULL) return 0;
2403 int hp = lua_tonumber(L, 2);
2404 infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
2405 <<" hp="<<hp<<std::endl;
2413 // returns: number of hitpoints (2 * number of hearts)
2414 // 0 if not applicable to this type of object
2415 static int l_get_hp(lua_State *L)
2417 ObjectRef *ref = checkobject(L, 1);
2418 ServerActiveObject *co = getobject(ref);
2419 if(co == NULL) return 0;
2420 int hp = co->getHP();
2421 infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
2422 <<" hp="<<hp<<std::endl;
2424 lua_pushnumber(L, hp);
2428 /* LuaEntitySAO-only */
2430 // setvelocity(self, {x=num, y=num, z=num})
2431 static int l_setvelocity(lua_State *L)
2433 ObjectRef *ref = checkobject(L, 1);
2434 LuaEntitySAO *co = getluaobject(ref);
2435 if(co == NULL) return 0;
2437 v3f pos = readFloatPos(L, 2);
2439 co->setVelocity(pos);
2443 // setacceleration(self, {x=num, y=num, z=num})
2444 static int l_setacceleration(lua_State *L)
2446 ObjectRef *ref = checkobject(L, 1);
2447 LuaEntitySAO *co = getluaobject(ref);
2448 if(co == NULL) return 0;
2450 v3f pos = readFloatPos(L, 2);
2452 co->setAcceleration(pos);
2456 // getacceleration(self)
2457 static int l_getacceleration(lua_State *L)
2459 ObjectRef *ref = checkobject(L, 1);
2460 LuaEntitySAO *co = getluaobject(ref);
2461 if(co == NULL) return 0;
2463 v3f v = co->getAcceleration();
2468 // settexturemod(self, mod)
2469 static int l_settexturemod(lua_State *L)
2471 ObjectRef *ref = checkobject(L, 1);
2472 LuaEntitySAO *co = getluaobject(ref);
2473 if(co == NULL) return 0;
2475 std::string mod = luaL_checkstring(L, 2);
2476 co->setTextureMod(mod);
2480 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
2481 // select_horiz_by_yawpitch=false)
2482 static int l_setsprite(lua_State *L)
2484 ObjectRef *ref = checkobject(L, 1);
2485 LuaEntitySAO *co = getluaobject(ref);
2486 if(co == NULL) return 0;
2489 if(!lua_isnil(L, 2))
2490 p = read_v2s16(L, 2);
2492 if(!lua_isnil(L, 3))
2493 num_frames = lua_tonumber(L, 3);
2494 float framelength = 0.2;
2495 if(!lua_isnil(L, 4))
2496 framelength = lua_tonumber(L, 4);
2497 bool select_horiz_by_yawpitch = false;
2498 if(!lua_isnil(L, 5))
2499 select_horiz_by_yawpitch = lua_toboolean(L, 5);
2500 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
2506 // get_player_name(self)
2507 static int l_get_player_name(lua_State *L)
2509 ObjectRef *ref = checkobject(L, 1);
2510 ServerRemotePlayer *player = getplayer(ref);
2516 lua_pushstring(L, player->getName());
2520 // inventory_set_list(self, name, {item1, item2, ...})
2521 static int l_inventory_set_list(lua_State *L)
2523 ObjectRef *ref = checkobject(L, 1);
2524 ServerRemotePlayer *player = getplayer(ref);
2525 if(player == NULL) return 0;
2526 const char *name = luaL_checkstring(L, 2);
2528 inventory_set_list_from_lua(&player->inventory, name, L, 3,
2529 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
2530 player->m_inventory_not_sent = true;
2534 // inventory_get_list(self, name)
2535 static int l_inventory_get_list(lua_State *L)
2537 ObjectRef *ref = checkobject(L, 1);
2538 ServerRemotePlayer *player = getplayer(ref);
2539 if(player == NULL) return 0;
2540 const char *name = luaL_checkstring(L, 2);
2542 inventory_get_list_to_lua(&player->inventory, name, L);
2546 // get_wielded_itemstring(self)
2547 static int l_get_wielded_itemstring(lua_State *L)
2549 ObjectRef *ref = checkobject(L, 1);
2550 ServerRemotePlayer *player = getplayer(ref);
2551 if(player == NULL) return 0;
2553 InventoryItem *item = player->getWieldedItem();
2558 lua_pushstring(L, item->getItemString().c_str());
2562 // get_wielded_item(self)
2563 static int l_get_wielded_item(lua_State *L)
2565 ObjectRef *ref = checkobject(L, 1);
2566 ServerRemotePlayer *player = getplayer(ref);
2567 if(player == NULL) return 0;
2569 InventoryItem *item0 = player->getWieldedItem();
2570 push_stack_item(L, item0);
2574 // get_look_dir(self)
2575 static int l_get_look_dir(lua_State *L)
2577 ObjectRef *ref = checkobject(L, 1);
2578 ServerRemotePlayer *player = getplayer(ref);
2579 if(player == NULL) return 0;
2581 float pitch = player->getRadPitch();
2582 float yaw = player->getRadYaw();
2583 v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
2588 // get_look_pitch(self)
2589 static int l_get_look_pitch(lua_State *L)
2591 ObjectRef *ref = checkobject(L, 1);
2592 ServerRemotePlayer *player = getplayer(ref);
2593 if(player == NULL) return 0;
2595 lua_pushnumber(L, player->getRadPitch());
2599 // get_look_yaw(self)
2600 static int l_get_look_yaw(lua_State *L)
2602 ObjectRef *ref = checkobject(L, 1);
2603 ServerRemotePlayer *player = getplayer(ref);
2604 if(player == NULL) return 0;
2606 lua_pushnumber(L, player->getRadYaw());
2611 ObjectRef(ServerActiveObject *object):
2614 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2620 infostream<<"ObjectRef destructing for id="
2621 <<m_object->getId()<<std::endl;
2623 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
2626 // Creates an ObjectRef and leaves it on top of stack
2627 // Not callable from Lua; all references are created on the C side.
2628 static void create(lua_State *L, ServerActiveObject *object)
2630 ObjectRef *o = new ObjectRef(object);
2631 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2632 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2633 luaL_getmetatable(L, className);
2634 lua_setmetatable(L, -2);
2637 static void set_null(lua_State *L)
2639 ObjectRef *o = checkobject(L, -1);
2643 static void Register(lua_State *L)
2646 int methodtable = lua_gettop(L);
2647 luaL_newmetatable(L, className);
2648 int metatable = lua_gettop(L);
2650 lua_pushliteral(L, "__metatable");
2651 lua_pushvalue(L, methodtable);
2652 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2654 lua_pushliteral(L, "__index");
2655 lua_pushvalue(L, methodtable);
2656 lua_settable(L, metatable);
2658 lua_pushliteral(L, "__gc");
2659 lua_pushcfunction(L, gc_object);
2660 lua_settable(L, metatable);
2662 lua_pop(L, 1); // drop metatable
2664 luaL_openlib(L, 0, methods, 0); // fill methodtable
2665 lua_pop(L, 1); // drop methodtable
2667 // Cannot be created from Lua
2668 //lua_register(L, className, create_object);
2671 const char ObjectRef::className[] = "ObjectRef";
2672 const luaL_reg ObjectRef::methods[] = {
2673 // ServerActiveObject
2674 method(ObjectRef, remove),
2675 method(ObjectRef, getpos),
2676 method(ObjectRef, setpos),
2677 method(ObjectRef, moveto),
2678 method(ObjectRef, punch),
2679 method(ObjectRef, right_click),
2680 method(ObjectRef, get_wield_digging_properties),
2681 method(ObjectRef, damage_wielded_item),
2682 method(ObjectRef, add_to_inventory),
2683 method(ObjectRef, add_to_inventory_later),
2684 method(ObjectRef, set_hp),
2685 method(ObjectRef, get_hp),
2686 // LuaEntitySAO-only
2687 method(ObjectRef, setvelocity),
2688 method(ObjectRef, setacceleration),
2689 method(ObjectRef, getacceleration),
2690 method(ObjectRef, settexturemod),
2691 method(ObjectRef, setsprite),
2693 method(ObjectRef, get_player_name),
2694 method(ObjectRef, inventory_set_list),
2695 method(ObjectRef, inventory_get_list),
2696 method(ObjectRef, get_wielded_itemstring),
2697 method(ObjectRef, get_wielded_item),
2698 method(ObjectRef, get_look_dir),
2699 method(ObjectRef, get_look_pitch),
2700 method(ObjectRef, get_look_yaw),
2704 // Creates a new anonymous reference if id=0
2705 static void objectref_get_or_create(lua_State *L,
2706 ServerActiveObject *cobj)
2708 if(cobj->getId() == 0){
2709 ObjectRef::create(L, cobj);
2711 objectref_get(L, cobj->getId());
2722 ServerEnvironment *m_env;
2724 static const char className[];
2725 static const luaL_reg methods[];
2727 static EnvRef *checkobject(lua_State *L, int narg)
2729 luaL_checktype(L, narg, LUA_TUSERDATA);
2730 void *ud = luaL_checkudata(L, narg, className);
2731 if(!ud) luaL_typerror(L, narg, className);
2732 return *(EnvRef**)ud; // unbox pointer
2735 // Exported functions
2737 // EnvRef:add_node(pos, node)
2738 // pos = {x=num, y=num, z=num}
2739 static int l_add_node(lua_State *L)
2741 //infostream<<"EnvRef::l_add_node()"<<std::endl;
2742 EnvRef *o = checkobject(L, 1);
2743 ServerEnvironment *env = o->m_env;
2744 if(env == NULL) return 0;
2746 v3s16 pos = readpos(L, 2);
2748 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
2750 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
2751 lua_pushboolean(L, succeeded);
2755 // EnvRef:remove_node(pos)
2756 // pos = {x=num, y=num, z=num}
2757 static int l_remove_node(lua_State *L)
2759 //infostream<<"EnvRef::l_remove_node()"<<std::endl;
2760 EnvRef *o = checkobject(L, 1);
2761 ServerEnvironment *env = o->m_env;
2762 if(env == NULL) return 0;
2764 v3s16 pos = readpos(L, 2);
2766 bool succeeded = env->getMap().removeNodeWithEvent(pos);
2767 lua_pushboolean(L, succeeded);
2771 // EnvRef:get_node(pos)
2772 // pos = {x=num, y=num, z=num}
2773 static int l_get_node(lua_State *L)
2775 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2776 EnvRef *o = checkobject(L, 1);
2777 ServerEnvironment *env = o->m_env;
2778 if(env == NULL) return 0;
2780 v3s16 pos = readpos(L, 2);
2782 MapNode n = env->getMap().getNodeNoEx(pos);
2784 pushnode(L, n, env->getGameDef()->ndef());
2788 // EnvRef:get_node_or_nil(pos)
2789 // pos = {x=num, y=num, z=num}
2790 static int l_get_node_or_nil(lua_State *L)
2792 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2793 EnvRef *o = checkobject(L, 1);
2794 ServerEnvironment *env = o->m_env;
2795 if(env == NULL) return 0;
2797 v3s16 pos = readpos(L, 2);
2800 MapNode n = env->getMap().getNode(pos);
2802 pushnode(L, n, env->getGameDef()->ndef());
2804 } catch(InvalidPositionException &e)
2811 // EnvRef:get_node_light(pos, timeofday)
2812 // pos = {x=num, y=num, z=num}
2813 // timeofday: nil = current time, 0 = night, 0.5 = day
2814 static int l_get_node_light(lua_State *L)
2816 EnvRef *o = checkobject(L, 1);
2817 ServerEnvironment *env = o->m_env;
2818 if(env == NULL) return 0;
2820 v3s16 pos = readpos(L, 2);
2821 u32 time_of_day = env->getTimeOfDay();
2822 if(lua_isnumber(L, 3))
2823 time_of_day = 24000.0 * lua_tonumber(L, 3);
2824 time_of_day %= 24000;
2825 u32 dnr = time_to_daynight_ratio(time_of_day);
2826 MapNode n = env->getMap().getNodeNoEx(pos);
2828 MapNode n = env->getMap().getNode(pos);
2829 INodeDefManager *ndef = env->getGameDef()->ndef();
2830 lua_pushinteger(L, n.getLightBlend(dnr, ndef));
2832 } catch(InvalidPositionException &e)
2839 // EnvRef:add_entity(pos, entityname)
2840 // pos = {x=num, y=num, z=num}
2841 static int l_add_entity(lua_State *L)
2843 //infostream<<"EnvRef::l_add_entity()"<<std::endl;
2844 EnvRef *o = checkobject(L, 1);
2845 ServerEnvironment *env = o->m_env;
2846 if(env == NULL) return 0;
2848 v3f pos = readFloatPos(L, 2);
2850 const char *name = luaL_checkstring(L, 3);
2852 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
2853 env->addActiveObject(obj);
2857 // EnvRef:add_item(pos, inventorystring)
2858 // pos = {x=num, y=num, z=num}
2859 static int l_add_item(lua_State *L)
2861 infostream<<"EnvRef::l_add_item()"<<std::endl;
2862 EnvRef *o = checkobject(L, 1);
2863 ServerEnvironment *env = o->m_env;
2864 if(env == NULL) return 0;
2866 v3f pos = readFloatPos(L, 2);
2868 const char *inventorystring = luaL_checkstring(L, 3);
2870 ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring);
2871 env->addActiveObject(obj);
2875 // EnvRef:add_rat(pos)
2876 // pos = {x=num, y=num, z=num}
2877 static int l_add_rat(lua_State *L)
2879 infostream<<"EnvRef::l_add_rat()"<<std::endl;
2880 EnvRef *o = checkobject(L, 1);
2881 ServerEnvironment *env = o->m_env;
2882 if(env == NULL) return 0;
2884 v3f pos = readFloatPos(L, 2);
2886 ServerActiveObject *obj = new RatSAO(env, pos);
2887 env->addActiveObject(obj);
2891 // EnvRef:add_firefly(pos)
2892 // pos = {x=num, y=num, z=num}
2893 static int l_add_firefly(lua_State *L)
2895 infostream<<"EnvRef::l_add_firefly()"<<std::endl;
2896 EnvRef *o = checkobject(L, 1);
2897 ServerEnvironment *env = o->m_env;
2898 if(env == NULL) return 0;
2900 v3f pos = readFloatPos(L, 2);
2902 ServerActiveObject *obj = new FireflySAO(env, pos);
2903 env->addActiveObject(obj);
2907 // EnvRef:get_meta(pos)
2908 static int l_get_meta(lua_State *L)
2910 //infostream<<"EnvRef::l_get_meta()"<<std::endl;
2911 EnvRef *o = checkobject(L, 1);
2912 ServerEnvironment *env = o->m_env;
2913 if(env == NULL) return 0;
2915 v3s16 p = readpos(L, 2);
2916 NodeMetaRef::create(L, p, env);
2920 // EnvRef:get_player_by_name(name)
2921 static int l_get_player_by_name(lua_State *L)
2923 EnvRef *o = checkobject(L, 1);
2924 ServerEnvironment *env = o->m_env;
2925 if(env == NULL) return 0;
2927 const char *name = luaL_checkstring(L, 2);
2928 ServerRemotePlayer *player =
2929 static_cast<ServerRemotePlayer*>(env->getPlayer(name));
2934 // Put player on stack
2935 objectref_get_or_create(L, player);
2939 // EnvRef:get_objects_inside_radius(pos, radius)
2940 static int l_get_objects_inside_radius(lua_State *L)
2942 // Get the table insert function
2943 lua_getglobal(L, "table");
2944 lua_getfield(L, -1, "insert");
2945 int table_insert = lua_gettop(L);
2947 EnvRef *o = checkobject(L, 1);
2948 ServerEnvironment *env = o->m_env;
2949 if(env == NULL) return 0;
2951 v3f pos = readFloatPos(L, 2);
2952 float radius = luaL_checknumber(L, 3) * BS;
2953 std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
2955 int table = lua_gettop(L);
2956 for(std::set<u16>::const_iterator
2957 i = ids.begin(); i != ids.end(); i++){
2958 ServerActiveObject *obj = env->getActiveObject(*i);
2959 // Insert object reference into table
2960 lua_pushvalue(L, table_insert);
2961 lua_pushvalue(L, table);
2962 objectref_get_or_create(L, obj);
2963 if(lua_pcall(L, 2, 0, 0))
2964 script_error(L, "error: %s", lua_tostring(L, -1));
2969 static int gc_object(lua_State *L) {
2970 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
2976 EnvRef(ServerEnvironment *env):
2979 infostream<<"EnvRef created"<<std::endl;
2984 infostream<<"EnvRef destructing"<<std::endl;
2987 // Creates an EnvRef and leaves it on top of stack
2988 // Not callable from Lua; all references are created on the C side.
2989 static void create(lua_State *L, ServerEnvironment *env)
2991 EnvRef *o = new EnvRef(env);
2992 //infostream<<"EnvRef::create: o="<<o<<std::endl;
2993 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2994 luaL_getmetatable(L, className);
2995 lua_setmetatable(L, -2);
2998 static void set_null(lua_State *L)
3000 EnvRef *o = checkobject(L, -1);
3004 static void Register(lua_State *L)
3007 int methodtable = lua_gettop(L);
3008 luaL_newmetatable(L, className);
3009 int metatable = lua_gettop(L);
3011 lua_pushliteral(L, "__metatable");
3012 lua_pushvalue(L, methodtable);
3013 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
3015 lua_pushliteral(L, "__index");
3016 lua_pushvalue(L, methodtable);
3017 lua_settable(L, metatable);
3019 lua_pushliteral(L, "__gc");
3020 lua_pushcfunction(L, gc_object);
3021 lua_settable(L, metatable);
3023 lua_pop(L, 1); // drop metatable
3025 luaL_openlib(L, 0, methods, 0); // fill methodtable
3026 lua_pop(L, 1); // drop methodtable
3028 // Cannot be created from Lua
3029 //lua_register(L, className, create_object);
3032 const char EnvRef::className[] = "EnvRef";
3033 const luaL_reg EnvRef::methods[] = {
3034 method(EnvRef, add_node),
3035 method(EnvRef, remove_node),
3036 method(EnvRef, get_node),
3037 method(EnvRef, get_node_or_nil),
3038 method(EnvRef, get_node_light),
3039 method(EnvRef, add_entity),
3040 method(EnvRef, add_item),
3041 method(EnvRef, add_rat),
3042 method(EnvRef, add_firefly),
3043 method(EnvRef, get_meta),
3044 method(EnvRef, get_player_by_name),
3045 method(EnvRef, get_objects_inside_radius),
3050 Main export function
3053 void scriptapi_export(lua_State *L, Server *server)
3056 assert(lua_checkstack(L, 20));
3057 infostream<<"scriptapi_export"<<std::endl;
3058 StackUnroller stack_unroller(L);
3060 // Store server as light userdata in registry
3061 lua_pushlightuserdata(L, server);
3062 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
3064 // Store nil as minetest_nodedef_defaults in registry
3066 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
3068 // Register global functions in table minetest
3070 luaL_register(L, NULL, minetest_f);
3071 lua_setglobal(L, "minetest");
3073 // Get the main minetest table
3074 lua_getglobal(L, "minetest");
3076 // Add tables to minetest
3079 lua_setfield(L, -2, "registered_nodes");
3081 lua_setfield(L, -2, "registered_entities");
3083 lua_setfield(L, -2, "registered_craftitems");
3085 lua_setfield(L, -2, "registered_abms");
3088 lua_setfield(L, -2, "object_refs");
3090 lua_setfield(L, -2, "luaentities");
3092 // Create entity prototype
3093 luaL_newmetatable(L, "minetest.entity");
3094 // metatable.__index = metatable
3095 lua_pushvalue(L, -1); // Duplicate metatable
3096 lua_setfield(L, -2, "__index");
3097 // Put functions in metatable
3098 luaL_register(L, NULL, minetest_entity_m);
3099 // Put other stuff in metatable
3101 // Register reference wrappers
3102 NodeMetaRef::Register(L);
3103 EnvRef::Register(L);
3104 ObjectRef::Register(L);
3107 bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
3108 const std::string &modname)
3110 ModNameStorer modnamestorer(L, modname);
3112 if(!string_allowed(modname, "abcdefghijklmnopqrstuvwxyz"
3114 errorstream<<"Error loading mod \""<<modname
3115 <<"\": modname does not follow naming conventions: "
3116 <<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
3120 bool success = false;
3123 success = script_load(L, scriptpath.c_str());
3126 errorstream<<"Error loading mod \""<<modname
3127 <<"\": "<<e.what()<<std::endl;
3133 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
3136 assert(lua_checkstack(L, 20));
3137 infostream<<"scriptapi_add_environment"<<std::endl;
3138 StackUnroller stack_unroller(L);
3140 // Create EnvRef on stack
3141 EnvRef::create(L, env);
3142 int envref = lua_gettop(L);
3144 // minetest.env = envref
3145 lua_getglobal(L, "minetest");
3146 luaL_checktype(L, -1, LUA_TTABLE);
3147 lua_pushvalue(L, envref);
3148 lua_setfield(L, -2, "env");
3150 // Store environment as light userdata in registry
3151 lua_pushlightuserdata(L, env);
3152 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
3155 Add ActiveBlockModifiers to environment
3158 // Get minetest.registered_abms
3159 lua_getglobal(L, "minetest");
3160 lua_getfield(L, -1, "registered_abms");
3161 luaL_checktype(L, -1, LUA_TTABLE);
3162 int registered_abms = lua_gettop(L);
3164 if(lua_istable(L, registered_abms)){
3165 int table = lua_gettop(L);
3167 while(lua_next(L, table) != 0){
3168 // key at index -2 and value at index -1
3169 int id = lua_tonumber(L, -2);
3170 int current_abm = lua_gettop(L);
3172 std::set<std::string> trigger_contents;
3173 lua_getfield(L, current_abm, "nodenames");
3174 if(lua_istable(L, -1)){
3175 int table = lua_gettop(L);
3177 while(lua_next(L, table) != 0){
3178 // key at index -2 and value at index -1
3179 luaL_checktype(L, -1, LUA_TSTRING);
3180 trigger_contents.insert(lua_tostring(L, -1));
3181 // removes value, keeps key for next iteration
3184 } else if(lua_isstring(L, -1)){
3185 trigger_contents.insert(lua_tostring(L, -1));
3189 std::set<std::string> required_neighbors;
3190 lua_getfield(L, current_abm, "neighbors");
3191 if(lua_istable(L, -1)){
3192 int table = lua_gettop(L);
3194 while(lua_next(L, table) != 0){
3195 // key at index -2 and value at index -1
3196 luaL_checktype(L, -1, LUA_TSTRING);
3197 required_neighbors.insert(lua_tostring(L, -1));
3198 // removes value, keeps key for next iteration
3201 } else if(lua_isstring(L, -1)){
3202 required_neighbors.insert(lua_tostring(L, -1));
3206 float trigger_interval = 10.0;
3207 getfloatfield(L, current_abm, "interval", trigger_interval);
3209 int trigger_chance = 50;
3210 getintfield(L, current_abm, "chance", trigger_chance);
3212 LuaABM *abm = new LuaABM(L, id, trigger_contents,
3213 required_neighbors, trigger_interval, trigger_chance);
3215 env->addActiveBlockModifier(abm);
3217 // removes value, keeps key for next iteration
3225 // Dump stack top with the dump2 function
3226 static void dump2(lua_State *L, const char *name)
3228 // Dump object (debug)
3229 lua_getglobal(L, "dump2");
3230 luaL_checktype(L, -1, LUA_TFUNCTION);
3231 lua_pushvalue(L, -2); // Get previous stack top as first parameter
3232 lua_pushstring(L, name);
3233 if(lua_pcall(L, 2, 0, 0))
3234 script_error(L, "error: %s", lua_tostring(L, -1));
3242 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
3245 assert(lua_checkstack(L, 20));
3246 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
3247 StackUnroller stack_unroller(L);
3249 // Create object on stack
3250 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
3251 int object = lua_gettop(L);
3253 // Get minetest.object_refs table
3254 lua_getglobal(L, "minetest");
3255 lua_getfield(L, -1, "object_refs");
3256 luaL_checktype(L, -1, LUA_TTABLE);
3257 int objectstable = lua_gettop(L);
3259 // object_refs[id] = object
3260 lua_pushnumber(L, cobj->getId()); // Push id
3261 lua_pushvalue(L, object); // Copy object to top of stack
3262 lua_settable(L, objectstable);
3265 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
3268 assert(lua_checkstack(L, 20));
3269 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
3270 StackUnroller stack_unroller(L);
3272 // Get minetest.object_refs table
3273 lua_getglobal(L, "minetest");
3274 lua_getfield(L, -1, "object_refs");
3275 luaL_checktype(L, -1, LUA_TTABLE);
3276 int objectstable = lua_gettop(L);
3278 // Get object_refs[id]
3279 lua_pushnumber(L, cobj->getId()); // Push id
3280 lua_gettable(L, objectstable);
3281 // Set object reference to NULL
3282 ObjectRef::set_null(L);
3283 lua_pop(L, 1); // pop object
3285 // Set object_refs[id] = nil
3286 lua_pushnumber(L, cobj->getId()); // Push id
3288 lua_settable(L, objectstable);
3291 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
3292 const std::string &message)
3295 assert(lua_checkstack(L, 20));
3296 StackUnroller stack_unroller(L);
3298 // Get minetest.registered_on_chat_messages
3299 lua_getglobal(L, "minetest");
3300 lua_getfield(L, -1, "registered_on_chat_messages");
3301 luaL_checktype(L, -1, LUA_TTABLE);
3302 int table = lua_gettop(L);
3305 while(lua_next(L, table) != 0){
3306 // key at index -2 and value at index -1
3307 luaL_checktype(L, -1, LUA_TFUNCTION);
3309 lua_pushstring(L, name.c_str());
3310 lua_pushstring(L, message.c_str());
3311 if(lua_pcall(L, 2, 1, 0))
3312 script_error(L, "error: %s", lua_tostring(L, -1));
3313 bool ate = lua_toboolean(L, -1);
3317 // value removed, keep key for next iteration
3326 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
3329 assert(lua_checkstack(L, 20));
3330 StackUnroller stack_unroller(L);
3332 // Get minetest.registered_on_newplayers
3333 lua_getglobal(L, "minetest");
3334 lua_getfield(L, -1, "registered_on_newplayers");
3335 luaL_checktype(L, -1, LUA_TTABLE);
3336 int table = lua_gettop(L);
3339 while(lua_next(L, table) != 0){
3340 // key at index -2 and value at index -1
3341 luaL_checktype(L, -1, LUA_TFUNCTION);
3343 objectref_get_or_create(L, player);
3344 if(lua_pcall(L, 1, 0, 0))
3345 script_error(L, "error: %s", lua_tostring(L, -1));
3346 // value removed, keep key for next iteration
3349 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
3352 assert(lua_checkstack(L, 20));
3353 StackUnroller stack_unroller(L);
3355 bool positioning_handled_by_some = false;
3357 // Get minetest.registered_on_respawnplayers
3358 lua_getglobal(L, "minetest");
3359 lua_getfield(L, -1, "registered_on_respawnplayers");
3360 luaL_checktype(L, -1, LUA_TTABLE);
3361 int table = lua_gettop(L);
3364 while(lua_next(L, table) != 0){
3365 // key at index -2 and value at index -1
3366 luaL_checktype(L, -1, LUA_TFUNCTION);
3368 objectref_get_or_create(L, player);
3369 if(lua_pcall(L, 1, 1, 0))
3370 script_error(L, "error: %s", lua_tostring(L, -1));
3371 bool positioning_handled = lua_toboolean(L, -1);
3373 if(positioning_handled)
3374 positioning_handled_by_some = true;
3375 // value removed, keep key for next iteration
3377 return positioning_handled_by_some;
3380 void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
3382 lua_getglobal(L, "minetest");
3383 lua_getfield(L, -1, "creative_inventory");
3384 luaL_checktype(L, -1, LUA_TTABLE);
3385 inventory_set_list_from_lua(&player->inventory, "main", L, -1,
3386 player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
3393 static void pushPointedThing(lua_State *L, const PointedThing& pointed)
3396 if(pointed.type == POINTEDTHING_NODE)
3398 lua_pushstring(L, "node");
3399 lua_setfield(L, -2, "type");
3400 pushpos(L, pointed.node_undersurface);
3401 lua_setfield(L, -2, "under");
3402 pushpos(L, pointed.node_abovesurface);
3403 lua_setfield(L, -2, "above");
3405 else if(pointed.type == POINTEDTHING_OBJECT)
3407 lua_pushstring(L, "object");
3408 lua_setfield(L, -2, "type");
3409 objectref_get(L, pointed.object_id);
3410 lua_setfield(L, -2, "ref");
3414 lua_pushstring(L, "nothing");
3415 lua_setfield(L, -2, "type");
3419 void scriptapi_add_craftitem(lua_State *L, const char *name)
3421 StackUnroller stack_unroller(L);
3422 assert(lua_gettop(L) > 0);
3424 // Set minetest.registered_craftitems[name] = table on top of stack
3425 lua_getglobal(L, "minetest");
3426 lua_getfield(L, -1, "registered_craftitems");
3427 luaL_checktype(L, -1, LUA_TTABLE);
3428 lua_pushvalue(L, -3); // push another reference to the table to be registered
3429 lua_setfield(L, -2, name); // set minetest.registered_craftitems[name]
3432 static bool get_craftitem_callback(lua_State *L, const char *name,
3433 const char *callbackname)
3435 // Get minetest.registered_craftitems[name][callbackname]
3436 // If that is nil or on error, return false and stack is unchanged
3437 // If that is a function, returns true and pushes the
3438 // function onto the stack
3440 lua_getglobal(L, "minetest");
3441 lua_getfield(L, -1, "registered_craftitems");
3443 luaL_checktype(L, -1, LUA_TTABLE);
3444 lua_getfield(L, -1, name);
3446 // Should be a table
3447 if(lua_type(L, -1) != LUA_TTABLE)
3449 errorstream<<"CraftItem name \""<<name<<"\" not defined"<<std::endl;
3453 lua_getfield(L, -1, callbackname);
3455 // Should be a function or nil
3456 if(lua_type(L, -1) == LUA_TFUNCTION)
3460 else if(lua_isnil(L, -1))
3467 errorstream<<"CraftItem name \""<<name<<"\" callback \""
3468 <<callbackname<<" is not a function"<<std::endl;
3474 bool scriptapi_craftitem_on_drop(lua_State *L, const char *name,
3475 ServerActiveObject *dropper, v3f pos,
3476 bool &callback_exists)
3479 assert(lua_checkstack(L, 20));
3480 //infostream<<"scriptapi_craftitem_on_drop"<<std::endl;
3481 StackUnroller stack_unroller(L);
3483 bool result = false;
3484 callback_exists = get_craftitem_callback(L, name, "on_drop");
3488 lua_pushstring(L, name);
3489 objectref_get_or_create(L, dropper);
3490 pushFloatPos(L, pos);
3491 if(lua_pcall(L, 3, 1, 0))
3492 script_error(L, "error: %s", lua_tostring(L, -1));
3493 result = lua_toboolean(L, -1);
3498 bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name,
3499 ServerActiveObject *placer, v3f pos,
3500 bool &callback_exists)
3503 assert(lua_checkstack(L, 20));
3504 //infostream<<"scriptapi_craftitem_on_place_on_ground"<<std::endl;
3505 StackUnroller stack_unroller(L);
3507 bool result = false;
3508 callback_exists = get_craftitem_callback(L, name, "on_place_on_ground");
3512 lua_pushstring(L, name);
3513 objectref_get_or_create(L, placer);
3514 pushFloatPos(L, pos);
3515 if(lua_pcall(L, 3, 1, 0))
3516 script_error(L, "error: %s", lua_tostring(L, -1));
3517 result = lua_toboolean(L, -1);
3522 bool scriptapi_craftitem_on_use(lua_State *L, const char *name,
3523 ServerActiveObject *user, const PointedThing& pointed,
3524 bool &callback_exists)
3527 assert(lua_checkstack(L, 20));
3528 //infostream<<"scriptapi_craftitem_on_use"<<std::endl;
3529 StackUnroller stack_unroller(L);
3531 bool result = false;
3532 callback_exists = get_craftitem_callback(L, name, "on_use");
3536 lua_pushstring(L, name);
3537 objectref_get_or_create(L, user);
3538 pushPointedThing(L, pointed);
3539 if(lua_pcall(L, 3, 1, 0))
3540 script_error(L, "error: %s", lua_tostring(L, -1));
3541 result = lua_toboolean(L, -1);
3550 void scriptapi_environment_step(lua_State *L, float dtime)
3553 assert(lua_checkstack(L, 20));
3554 //infostream<<"scriptapi_environment_step"<<std::endl;
3555 StackUnroller stack_unroller(L);
3557 // Get minetest.registered_globalsteps
3558 lua_getglobal(L, "minetest");
3559 lua_getfield(L, -1, "registered_globalsteps");
3560 luaL_checktype(L, -1, LUA_TTABLE);
3561 int table = lua_gettop(L);
3564 while(lua_next(L, table) != 0){
3565 // key at index -2 and value at index -1
3566 luaL_checktype(L, -1, LUA_TFUNCTION);
3568 lua_pushnumber(L, dtime);
3569 if(lua_pcall(L, 1, 0, 0))
3570 script_error(L, "error: %s", lua_tostring(L, -1));
3571 // value removed, keep key for next iteration
3575 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
3576 ServerActiveObject *placer)
3579 assert(lua_checkstack(L, 20));
3580 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
3581 StackUnroller stack_unroller(L);
3583 // Get the writable node definition manager from the server
3584 IWritableNodeDefManager *ndef =
3585 get_server(L)->getWritableNodeDefManager();
3587 // Get minetest.registered_on_placenodes
3588 lua_getglobal(L, "minetest");
3589 lua_getfield(L, -1, "registered_on_placenodes");
3590 luaL_checktype(L, -1, LUA_TTABLE);
3591 int table = lua_gettop(L);
3594 while(lua_next(L, table) != 0){
3595 // key at index -2 and value at index -1
3596 luaL_checktype(L, -1, LUA_TFUNCTION);
3599 pushnode(L, newnode, ndef);
3600 objectref_get_or_create(L, placer);
3601 if(lua_pcall(L, 3, 0, 0))
3602 script_error(L, "error: %s", lua_tostring(L, -1));
3603 // value removed, keep key for next iteration
3607 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
3608 ServerActiveObject *digger)
3611 assert(lua_checkstack(L, 20));
3612 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
3613 StackUnroller stack_unroller(L);
3615 // Get the writable node definition manager from the server
3616 IWritableNodeDefManager *ndef =
3617 get_server(L)->getWritableNodeDefManager();
3619 // Get minetest.registered_on_dignodes
3620 lua_getglobal(L, "minetest");
3621 lua_getfield(L, -1, "registered_on_dignodes");
3622 luaL_checktype(L, -1, LUA_TTABLE);
3623 int table = lua_gettop(L);
3626 while(lua_next(L, table) != 0){
3627 // key at index -2 and value at index -1
3628 luaL_checktype(L, -1, LUA_TFUNCTION);
3631 pushnode(L, oldnode, ndef);
3632 objectref_get_or_create(L, digger);
3633 if(lua_pcall(L, 3, 0, 0))
3634 script_error(L, "error: %s", lua_tostring(L, -1));
3635 // value removed, keep key for next iteration
3639 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
3640 ServerActiveObject *puncher)
3643 assert(lua_checkstack(L, 20));
3644 //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
3645 StackUnroller stack_unroller(L);
3647 // Get the writable node definition manager from the server
3648 IWritableNodeDefManager *ndef =
3649 get_server(L)->getWritableNodeDefManager();
3651 // Get minetest.registered_on_punchnodes
3652 lua_getglobal(L, "minetest");
3653 lua_getfield(L, -1, "registered_on_punchnodes");
3654 luaL_checktype(L, -1, LUA_TTABLE);
3655 int table = lua_gettop(L);
3658 while(lua_next(L, table) != 0){
3659 // key at index -2 and value at index -1
3660 luaL_checktype(L, -1, LUA_TFUNCTION);
3663 pushnode(L, node, ndef);
3664 objectref_get_or_create(L, puncher);
3665 if(lua_pcall(L, 3, 0, 0))
3666 script_error(L, "error: %s", lua_tostring(L, -1));
3667 // value removed, keep key for next iteration
3671 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
3674 assert(lua_checkstack(L, 20));
3675 //infostream<<"scriptapi_environment_on_generated"<<std::endl;
3676 StackUnroller stack_unroller(L);
3678 // Get minetest.registered_on_generateds
3679 lua_getglobal(L, "minetest");
3680 lua_getfield(L, -1, "registered_on_generateds");
3681 luaL_checktype(L, -1, LUA_TTABLE);
3682 int table = lua_gettop(L);
3685 while(lua_next(L, table) != 0){
3686 // key at index -2 and value at index -1
3687 luaL_checktype(L, -1, LUA_TFUNCTION);
3691 if(lua_pcall(L, 2, 0, 0))
3692 script_error(L, "error: %s", lua_tostring(L, -1));
3693 // value removed, keep key for next iteration
3701 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
3702 const std::string &staticdata)
3705 assert(lua_checkstack(L, 20));
3706 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
3707 <<name<<"\""<<std::endl;
3708 StackUnroller stack_unroller(L);
3710 // Get minetest.registered_entities[name]
3711 lua_getglobal(L, "minetest");
3712 lua_getfield(L, -1, "registered_entities");
3713 luaL_checktype(L, -1, LUA_TTABLE);
3714 lua_pushstring(L, name);
3715 lua_gettable(L, -2);
3716 // Should be a table, which we will use as a prototype
3717 //luaL_checktype(L, -1, LUA_TTABLE);
3718 if(lua_type(L, -1) != LUA_TTABLE){
3719 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
3722 int prototype_table = lua_gettop(L);
3723 //dump2(L, "prototype_table");
3725 // Create entity object
3727 int object = lua_gettop(L);
3729 // Set object metatable
3730 lua_pushvalue(L, prototype_table);
3731 lua_setmetatable(L, -2);
3733 // Add object reference
3734 // This should be userdata with metatable ObjectRef
3735 objectref_get(L, id);
3736 luaL_checktype(L, -1, LUA_TUSERDATA);
3737 if(!luaL_checkudata(L, -1, "ObjectRef"))
3738 luaL_typerror(L, -1, "ObjectRef");
3739 lua_setfield(L, -2, "object");
3741 // minetest.luaentities[id] = object
3742 lua_getglobal(L, "minetest");
3743 lua_getfield(L, -1, "luaentities");
3744 luaL_checktype(L, -1, LUA_TTABLE);
3745 lua_pushnumber(L, id); // Push id
3746 lua_pushvalue(L, object); // Copy object to top of stack
3747 lua_settable(L, -3);
3749 // Get on_activate function
3750 lua_pushvalue(L, object);
3751 lua_getfield(L, -1, "on_activate");
3752 if(!lua_isnil(L, -1)){
3753 luaL_checktype(L, -1, LUA_TFUNCTION);
3754 lua_pushvalue(L, object); // self
3755 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
3756 // Call with 2 arguments, 0 results
3757 if(lua_pcall(L, 2, 0, 0))
3758 script_error(L, "error running function %s:on_activate: %s\n",
3759 name, lua_tostring(L, -1));
3765 void scriptapi_luaentity_rm(lua_State *L, u16 id)
3768 assert(lua_checkstack(L, 20));
3769 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
3771 // Get minetest.luaentities table
3772 lua_getglobal(L, "minetest");
3773 lua_getfield(L, -1, "luaentities");
3774 luaL_checktype(L, -1, LUA_TTABLE);
3775 int objectstable = lua_gettop(L);
3777 // Set luaentities[id] = nil
3778 lua_pushnumber(L, id); // Push id
3780 lua_settable(L, objectstable);
3782 lua_pop(L, 2); // pop luaentities, minetest
3785 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
3788 assert(lua_checkstack(L, 20));
3789 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
3790 StackUnroller stack_unroller(L);
3792 // Get minetest.luaentities[id]
3793 luaentity_get(L, id);
3794 int object = lua_gettop(L);
3796 // Get get_staticdata function
3797 lua_pushvalue(L, object);
3798 lua_getfield(L, -1, "get_staticdata");
3799 if(lua_isnil(L, -1))
3802 luaL_checktype(L, -1, LUA_TFUNCTION);
3803 lua_pushvalue(L, object); // self
3804 // Call with 1 arguments, 1 results
3805 if(lua_pcall(L, 1, 1, 0))
3806 script_error(L, "error running function get_staticdata: %s\n",
3807 lua_tostring(L, -1));
3810 const char *s = lua_tolstring(L, -1, &len);
3811 return std::string(s, len);
3814 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
3815 LuaEntityProperties *prop)
3818 assert(lua_checkstack(L, 20));
3819 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
3820 StackUnroller stack_unroller(L);
3822 // Get minetest.luaentities[id]
3823 luaentity_get(L, id);
3824 //int object = lua_gettop(L);
3828 getboolfield(L, -1, "physical", prop->physical);
3830 getfloatfield(L, -1, "weight", prop->weight);
3832 lua_getfield(L, -1, "collisionbox");
3833 if(lua_istable(L, -1))
3834 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
3837 getstringfield(L, -1, "visual", prop->visual);
3839 lua_getfield(L, -1, "visual_size");
3840 if(lua_istable(L, -1))
3841 prop->visual_size = read_v2f(L, -1);
3844 lua_getfield(L, -1, "textures");
3845 if(lua_istable(L, -1)){
3846 prop->textures.clear();
3847 int table = lua_gettop(L);
3849 while(lua_next(L, table) != 0){
3850 // key at index -2 and value at index -1
3851 if(lua_isstring(L, -1))
3852 prop->textures.push_back(lua_tostring(L, -1));
3854 prop->textures.push_back("");
3855 // removes value, keeps key for next iteration
3861 lua_getfield(L, -1, "spritediv");
3862 if(lua_istable(L, -1))
3863 prop->spritediv = read_v2s16(L, -1);
3866 lua_getfield(L, -1, "initial_sprite_basepos");
3867 if(lua_istable(L, -1))
3868 prop->initial_sprite_basepos = read_v2s16(L, -1);
3872 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
3875 assert(lua_checkstack(L, 20));
3876 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3877 StackUnroller stack_unroller(L);
3879 // Get minetest.luaentities[id]
3880 luaentity_get(L, id);
3881 int object = lua_gettop(L);
3882 // State: object is at top of stack
3883 // Get step function
3884 lua_getfield(L, -1, "on_step");
3885 if(lua_isnil(L, -1))
3887 luaL_checktype(L, -1, LUA_TFUNCTION);
3888 lua_pushvalue(L, object); // self
3889 lua_pushnumber(L, dtime); // dtime
3890 // Call with 2 arguments, 0 results
3891 if(lua_pcall(L, 2, 0, 0))
3892 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
3895 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
3896 void scriptapi_luaentity_punch(lua_State *L, u16 id,
3897 ServerActiveObject *puncher, float time_from_last_punch)
3900 assert(lua_checkstack(L, 20));
3901 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3902 StackUnroller stack_unroller(L);
3904 // Get minetest.luaentities[id]
3905 luaentity_get(L, id);
3906 int object = lua_gettop(L);
3907 // State: object is at top of stack
3909 lua_getfield(L, -1, "on_punch");
3910 if(lua_isnil(L, -1))
3912 luaL_checktype(L, -1, LUA_TFUNCTION);
3913 lua_pushvalue(L, object); // self
3914 objectref_get_or_create(L, puncher); // Clicker reference
3915 lua_pushnumber(L, time_from_last_punch);
3916 // Call with 2 arguments, 0 results
3917 if(lua_pcall(L, 3, 0, 0))
3918 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
3921 // Calls entity:on_rightclick(ObjectRef clicker)
3922 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
3923 ServerActiveObject *clicker)
3926 assert(lua_checkstack(L, 20));
3927 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
3928 StackUnroller stack_unroller(L);
3930 // Get minetest.luaentities[id]
3931 luaentity_get(L, id);
3932 int object = lua_gettop(L);
3933 // State: object is at top of stack
3935 lua_getfield(L, -1, "on_rightclick");
3936 if(lua_isnil(L, -1))
3938 luaL_checktype(L, -1, LUA_TFUNCTION);
3939 lua_pushvalue(L, object); // self
3940 objectref_get_or_create(L, clicker); // Clicker reference
3941 // Call with 2 arguments, 0 results
3942 if(lua_pcall(L, 2, 0, 0))
3943 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));