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 "main.h" // For g_settings
43 #include "settings.h" // For accessing g_settings
44 #include "nodemetadata.h"
45 #include "mapblock.h" // For getNodeBlockPos
46 #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");
131 Getters for stuff in main tables
134 static Server* get_server(lua_State *L)
136 // Get server from registry
137 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
138 Server *server = (Server*)lua_touserdata(L, -1);
143 static ServerEnvironment* get_env(lua_State *L)
145 // Get environment from registry
146 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
147 ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
152 static void objectref_get(lua_State *L, u16 id)
154 // Get minetest.object_refs[i]
155 lua_getglobal(L, "minetest");
156 lua_getfield(L, -1, "object_refs");
157 luaL_checktype(L, -1, LUA_TTABLE);
158 lua_pushnumber(L, id);
160 lua_remove(L, -2); // object_refs
161 lua_remove(L, -2); // minetest
164 static void luaentity_get(lua_State *L, u16 id)
166 // Get minetest.luaentities[i]
167 lua_getglobal(L, "minetest");
168 lua_getfield(L, -1, "luaentities");
169 luaL_checktype(L, -1, LUA_TTABLE);
170 lua_pushnumber(L, id);
172 lua_remove(L, -2); // luaentities
173 lua_remove(L, -2); // minetest
180 static bool getstringfield(lua_State *L, int table,
181 const char *fieldname, std::string &result)
183 lua_getfield(L, table, fieldname);
185 if(lua_isstring(L, -1)){
187 const char *ptr = lua_tolstring(L, -1, &len);
188 result.assign(ptr, len);
195 static bool getintfield(lua_State *L, int table,
196 const char *fieldname, int &result)
198 lua_getfield(L, table, fieldname);
200 if(lua_isnumber(L, -1)){
201 result = lua_tonumber(L, -1);
208 static bool getfloatfield(lua_State *L, int table,
209 const char *fieldname, float &result)
211 lua_getfield(L, table, fieldname);
213 if(lua_isnumber(L, -1)){
214 result = lua_tonumber(L, -1);
221 static bool getboolfield(lua_State *L, int table,
222 const char *fieldname, bool &result)
224 lua_getfield(L, table, fieldname);
226 if(lua_isboolean(L, -1)){
227 result = lua_toboolean(L, -1);
234 static std::string checkstringfield(lua_State *L, int table,
235 const char *fieldname)
237 lua_getfield(L, table, fieldname);
238 std::string s = luaL_checkstring(L, -1);
243 static std::string getstringfield_default(lua_State *L, int table,
244 const char *fieldname, const std::string &default_)
246 std::string result = default_;
247 getstringfield(L, table, fieldname, result);
251 static int getintfield_default(lua_State *L, int table,
252 const char *fieldname, int default_)
254 int result = default_;
255 getintfield(L, table, fieldname, result);
259 static float getfloatfield_default(lua_State *L, int table,
260 const char *fieldname, float default_)
262 float result = default_;
263 getfloatfield(L, table, fieldname, result);
267 static bool getboolfield_default(lua_State *L, int table,
268 const char *fieldname, bool default_)
270 bool result = default_;
271 getboolfield(L, table, fieldname, result);
281 static bool string_to_enum(const EnumString *spec, int &result,
282 const std::string &str)
284 const EnumString *esp = spec;
286 if(str == std::string(esp->str)){
295 /*static bool enum_to_string(const EnumString *spec, std::string &result,
298 const EnumString *esp = spec;
309 static int getenumfield(lua_State *L, int table,
310 const char *fieldname, const EnumString *spec, int default_)
312 int result = default_;
313 string_to_enum(spec, result,
314 getstringfield_default(L, table, fieldname, ""));
318 static void setintfield(lua_State *L, int table,
319 const char *fieldname, int value)
321 lua_pushinteger(L, value);
324 lua_setfield(L, table, fieldname);
327 static void setfloatfield(lua_State *L, int table,
328 const char *fieldname, float value)
330 lua_pushnumber(L, value);
333 lua_setfield(L, table, fieldname);
336 static void setboolfield(lua_State *L, int table,
337 const char *fieldname, bool value)
339 lua_pushboolean(L, value);
342 lua_setfield(L, table, fieldname);
345 static void warn_if_field_exists(lua_State *L, int table,
346 const char *fieldname, const std::string &message)
348 lua_getfield(L, table, fieldname);
349 if(!lua_isnil(L, -1)){
350 infostream<<script_get_backtrace(L)<<std::endl;
351 infostream<<"WARNING: field \""<<fieldname<<"\": "
352 <<message<<std::endl;
358 EnumString definitions
361 struct EnumString es_ItemType[] =
365 {ITEM_CRAFT, "craft"},
370 struct EnumString es_DrawType[] =
372 {NDT_NORMAL, "normal"},
373 {NDT_AIRLIKE, "airlike"},
374 {NDT_LIQUID, "liquid"},
375 {NDT_FLOWINGLIQUID, "flowingliquid"},
376 {NDT_GLASSLIKE, "glasslike"},
377 {NDT_ALLFACES, "allfaces"},
378 {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
379 {NDT_TORCHLIKE, "torchlike"},
380 {NDT_SIGNLIKE, "signlike"},
381 {NDT_PLANTLIKE, "plantlike"},
382 {NDT_FENCELIKE, "fencelike"},
383 {NDT_RAILLIKE, "raillike"},
387 struct EnumString es_ContentParamType[] =
390 {CPT_LIGHT, "light"},
394 struct EnumString es_ContentParamType2[] =
398 {CPT2_FLOWINGLIQUID, "flowingliquid"},
399 {CPT2_FACEDIR, "facedir"},
400 {CPT2_WALLMOUNTED, "wallmounted"},
404 struct EnumString es_LiquidType[] =
406 {LIQUID_NONE, "none"},
407 {LIQUID_FLOWING, "flowing"},
408 {LIQUID_SOURCE, "source"},
412 struct EnumString es_NodeBoxType[] =
414 {NODEBOX_REGULAR, "regular"},
415 {NODEBOX_FIXED, "fixed"},
416 {NODEBOX_WALLMOUNTED, "wallmounted"},
421 C struct <-> Lua table converter functions
424 static void push_v3f(lua_State *L, v3f p)
427 lua_pushnumber(L, p.X);
428 lua_setfield(L, -2, "x");
429 lua_pushnumber(L, p.Y);
430 lua_setfield(L, -2, "y");
431 lua_pushnumber(L, p.Z);
432 lua_setfield(L, -2, "z");
435 static v2s16 read_v2s16(lua_State *L, int index)
438 luaL_checktype(L, index, LUA_TTABLE);
439 lua_getfield(L, index, "x");
440 p.X = lua_tonumber(L, -1);
442 lua_getfield(L, index, "y");
443 p.Y = lua_tonumber(L, -1);
448 static v2f read_v2f(lua_State *L, int index)
451 luaL_checktype(L, index, LUA_TTABLE);
452 lua_getfield(L, index, "x");
453 p.X = lua_tonumber(L, -1);
455 lua_getfield(L, index, "y");
456 p.Y = lua_tonumber(L, -1);
461 static v3f read_v3f(lua_State *L, int index)
464 luaL_checktype(L, index, LUA_TTABLE);
465 lua_getfield(L, index, "x");
466 pos.X = lua_tonumber(L, -1);
468 lua_getfield(L, index, "y");
469 pos.Y = lua_tonumber(L, -1);
471 lua_getfield(L, index, "z");
472 pos.Z = lua_tonumber(L, -1);
477 static v3f check_v3f(lua_State *L, int index)
480 luaL_checktype(L, index, LUA_TTABLE);
481 lua_getfield(L, index, "x");
482 pos.X = luaL_checknumber(L, -1);
484 lua_getfield(L, index, "y");
485 pos.Y = luaL_checknumber(L, -1);
487 lua_getfield(L, index, "z");
488 pos.Z = luaL_checknumber(L, -1);
493 static void pushFloatPos(lua_State *L, v3f p)
499 static v3f checkFloatPos(lua_State *L, int index)
501 return check_v3f(L, index) * BS;
504 static void push_v3s16(lua_State *L, v3s16 p)
507 lua_pushnumber(L, p.X);
508 lua_setfield(L, -2, "x");
509 lua_pushnumber(L, p.Y);
510 lua_setfield(L, -2, "y");
511 lua_pushnumber(L, p.Z);
512 lua_setfield(L, -2, "z");
515 static v3s16 read_v3s16(lua_State *L, int index)
517 // Correct rounding at <0
518 v3f pf = read_v3f(L, index);
519 return floatToInt(pf, 1.0);
522 static v3s16 check_v3s16(lua_State *L, int index)
524 // Correct rounding at <0
525 v3f pf = check_v3f(L, index);
526 return floatToInt(pf, 1.0);
529 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
532 lua_pushstring(L, ndef->get(n).name.c_str());
533 lua_setfield(L, -2, "name");
534 lua_pushnumber(L, n.getParam1());
535 lua_setfield(L, -2, "param1");
536 lua_pushnumber(L, n.getParam2());
537 lua_setfield(L, -2, "param2");
540 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
542 lua_getfield(L, index, "name");
543 const char *name = luaL_checkstring(L, -1);
546 lua_getfield(L, index, "param1");
550 param1 = lua_tonumber(L, -1);
553 lua_getfield(L, index, "param2");
557 param2 = lua_tonumber(L, -1);
559 return MapNode(ndef, name, param1, param2);
562 static video::SColor readARGB8(lua_State *L, int index)
565 luaL_checktype(L, index, LUA_TTABLE);
566 lua_getfield(L, index, "a");
567 if(lua_isnumber(L, -1))
568 color.setAlpha(lua_tonumber(L, -1));
570 lua_getfield(L, index, "r");
571 color.setRed(lua_tonumber(L, -1));
573 lua_getfield(L, index, "g");
574 color.setGreen(lua_tonumber(L, -1));
576 lua_getfield(L, index, "b");
577 color.setBlue(lua_tonumber(L, -1));
582 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
584 core::aabbox3d<f32> box;
585 if(lua_istable(L, -1)){
586 lua_rawgeti(L, -1, 1);
587 box.MinEdge.X = lua_tonumber(L, -1) * scale;
589 lua_rawgeti(L, -1, 2);
590 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
592 lua_rawgeti(L, -1, 3);
593 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
595 lua_rawgeti(L, -1, 4);
596 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
598 lua_rawgeti(L, -1, 5);
599 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
601 lua_rawgeti(L, -1, 6);
602 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
613 static MaterialProperties read_material_properties(
614 lua_State *L, int table)
616 MaterialProperties prop;
617 prop.diggability = (Diggability)getenumfield(L, -1, "diggability",
618 es_Diggability, DIGGABLE_NORMAL);
619 getfloatfield(L, -1, "constant_time", prop.constant_time);
620 getfloatfield(L, -1, "weight", prop.weight);
621 getfloatfield(L, -1, "crackiness", prop.crackiness);
622 getfloatfield(L, -1, "crumbliness", prop.crumbliness);
623 getfloatfield(L, -1, "cuttability", prop.cuttability);
624 getfloatfield(L, -1, "flammability", prop.flammability);
632 static void read_groups(lua_State *L, int index,
633 std::map<std::string, int> &result)
639 while(lua_next(L, index) != 0){
640 // key at index -2 and value at index -1
641 std::string name = luaL_checkstring(L, -2);
642 int rating = luaL_checkinteger(L, -1);
643 result[name] = rating;
644 // removes value, keeps key for next iteration
653 static ToolCapabilities read_tool_capabilities(
654 lua_State *L, int table)
656 ToolCapabilities toolcap;
657 getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
658 getintfield(L, table, "max_drop_level", toolcap.max_drop_level);
659 lua_getfield(L, table, "groupcaps");
660 if(lua_istable(L, -1)){
661 int table_groupcaps = lua_gettop(L);
663 while(lua_next(L, table_groupcaps) != 0){
664 // key at index -2 and value at index -1
665 std::string groupname = luaL_checkstring(L, -2);
666 if(lua_istable(L, -1)){
667 int table_groupcap = lua_gettop(L);
668 // This will be created
669 ToolGroupCap groupcap;
670 // Read simple parameters
671 getfloatfield(L, table_groupcap, "maxwear", groupcap.maxwear);
672 getintfield(L, table_groupcap, "maxlevel", groupcap.maxlevel);
673 // Read "times" table
674 lua_getfield(L, table_groupcap, "times");
675 if(lua_istable(L, -1)){
676 int table_times = lua_gettop(L);
678 while(lua_next(L, table_times) != 0){
679 // key at index -2 and value at index -1
680 int rating = luaL_checkinteger(L, -2);
681 float time = luaL_checknumber(L, -1);
682 groupcap.times[rating] = time;
683 // removes value, keeps key for next iteration
688 // Insert groupcap into toolcap
689 toolcap.groupcaps[groupname] = groupcap;
691 // removes value, keeps key for next iteration
699 static void set_tool_capabilities(lua_State *L, int table,
700 const ToolCapabilities &toolcap)
702 setfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval);
703 setintfield(L, table, "max_drop_level", toolcap.max_drop_level);
704 // Create groupcaps table
707 for(std::map<std::string, ToolGroupCap>::const_iterator
708 i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
709 // Create groupcap table
711 const std::string &name = i->first;
712 const ToolGroupCap &groupcap = i->second;
713 // Create subtable "times"
715 for(std::map<int, float>::const_iterator
716 i = groupcap.times.begin(); i != groupcap.times.end(); i++){
717 int rating = i->first;
718 float time = i->second;
719 lua_pushinteger(L, rating);
720 lua_pushnumber(L, time);
723 // Set subtable "times"
724 lua_setfield(L, -2, "times");
725 // Set simple parameters
726 setfloatfield(L, -1, "maxwear", groupcap.maxwear);
727 setintfield(L, -1, "maxlevel", groupcap.maxlevel);
728 // Insert groupcap table into groupcaps table
729 lua_setfield(L, -2, name.c_str());
731 // Set groupcaps table
732 lua_setfield(L, -2, "groupcaps");
735 static void push_tool_capabilities(lua_State *L,
736 const ToolCapabilities &prop)
739 set_tool_capabilities(L, -1, prop);
746 static void set_dig_params(lua_State *L, int table,
747 const DigParams ¶ms)
749 setboolfield(L, table, "diggable", params.diggable);
750 setfloatfield(L, table, "time", params.time);
751 setintfield(L, table, "wear", params.wear);
754 static void push_dig_params(lua_State *L,
755 const DigParams ¶ms)
758 set_dig_params(L, -1, params);
765 static void set_hit_params(lua_State *L, int table,
766 const HitParams ¶ms)
768 setintfield(L, table, "hp", params.hp);
769 setintfield(L, table, "wear", params.wear);
772 static void push_hit_params(lua_State *L,
773 const HitParams ¶ms)
776 set_hit_params(L, -1, params);
783 static void push_pointed_thing(lua_State *L, const PointedThing& pointed)
786 if(pointed.type == POINTEDTHING_NODE)
788 lua_pushstring(L, "node");
789 lua_setfield(L, -2, "type");
790 push_v3s16(L, pointed.node_undersurface);
791 lua_setfield(L, -2, "under");
792 push_v3s16(L, pointed.node_abovesurface);
793 lua_setfield(L, -2, "above");
795 else if(pointed.type == POINTEDTHING_OBJECT)
797 lua_pushstring(L, "object");
798 lua_setfield(L, -2, "type");
799 objectref_get(L, pointed.object_id);
800 lua_setfield(L, -2, "ref");
804 lua_pushstring(L, "nothing");
805 lua_setfield(L, -2, "type");
813 static ItemDefinition read_item_definition(lua_State *L, int index)
816 index = lua_gettop(L) + 1 + index;
818 // Read the item definition
821 def.type = (ItemType)getenumfield(L, index, "type",
822 es_ItemType, ITEM_NONE);
823 getstringfield(L, index, "name", def.name);
824 getstringfield(L, index, "description", def.description);
825 getstringfield(L, index, "inventory_image", def.inventory_image);
826 getstringfield(L, index, "wield_image", def.wield_image);
828 lua_getfield(L, index, "wield_scale");
829 if(lua_istable(L, -1)){
830 def.wield_scale = check_v3f(L, -1);
834 def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
835 if(def.stack_max == 0)
838 lua_getfield(L, index, "on_use");
839 def.usable = lua_isfunction(L, -1);
842 getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
844 warn_if_field_exists(L, index, "tool_digging_properties",
845 "deprecated: use tool_capabilities");
847 lua_getfield(L, index, "tool_capabilities");
848 if(lua_istable(L, -1)){
849 def.tool_capabilities = new ToolCapabilities(
850 read_tool_capabilities(L, -1));
853 // If name is "" (hand), ensure there are ToolCapabilities
854 // because it will be looked up there whenever any other item has
855 // no ToolCapabilities
856 if(def.name == "" && def.tool_capabilities == NULL){
857 def.tool_capabilities = new ToolCapabilities();
860 lua_getfield(L, index, "groups");
861 read_groups(L, -1, def.groups);
871 static ContentFeatures read_content_features(lua_State *L, int index)
874 index = lua_gettop(L) + 1 + index;
878 getstringfield(L, index, "name", f.name);
881 lua_getfield(L, index, "groups");
882 read_groups(L, -1, f.groups);
885 /* Visual definition */
887 f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType,
889 getfloatfield(L, index, "visual_scale", f.visual_scale);
891 lua_getfield(L, index, "tile_images");
892 if(lua_istable(L, -1)){
893 int table = lua_gettop(L);
896 while(lua_next(L, table) != 0){
897 // key at index -2 and value at index -1
898 if(lua_isstring(L, -1))
899 f.tname_tiles[i] = lua_tostring(L, -1);
901 f.tname_tiles[i] = "";
902 // removes value, keeps key for next iteration
910 // Copy last value to all remaining textures
912 std::string lastname = f.tname_tiles[i-1];
914 f.tname_tiles[i] = lastname;
921 lua_getfield(L, index, "special_materials");
922 if(lua_istable(L, -1)){
923 int table = lua_gettop(L);
926 while(lua_next(L, table) != 0){
927 // key at index -2 and value at index -1
928 int smtable = lua_gettop(L);
929 std::string tname = getstringfield_default(
930 L, smtable, "image", "");
931 bool backface_culling = getboolfield_default(
932 L, smtable, "backface_culling", true);
933 MaterialSpec mspec(tname, backface_culling);
934 f.mspec_special[i] = mspec;
935 // removes value, keeps key for next iteration
946 f.alpha = getintfield_default(L, index, "alpha", 255);
950 lua_getfield(L, index, "post_effect_color");
951 if(!lua_isnil(L, -1))
952 f.post_effect_color = readARGB8(L, -1);
955 f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
956 es_ContentParamType, CPT_NONE);
957 f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
958 es_ContentParamType2, CPT2_NONE);
960 // Warn about some deprecated fields
961 warn_if_field_exists(L, index, "wall_mounted",
962 "deprecated: use paramtype2 = 'wallmounted'");
963 warn_if_field_exists(L, index, "light_propagates",
964 "deprecated: determined from paramtype");
965 warn_if_field_exists(L, index, "dug_item",
966 "deprecated: use 'drop' field");
967 warn_if_field_exists(L, index, "extra_dug_item",
968 "deprecated: use 'drop' field");
969 warn_if_field_exists(L, index, "extra_dug_item_rarity",
970 "deprecated: use 'drop' field");
972 // True for all ground-like things like stone and mud, false for eg. trees
973 getboolfield(L, index, "is_ground_content", f.is_ground_content);
974 f.light_propagates = (f.param_type == CPT_LIGHT);
975 getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
976 // This is used for collision detection.
977 // Also for general solidness queries.
978 getboolfield(L, index, "walkable", f.walkable);
979 // Player can point to these
980 getboolfield(L, index, "pointable", f.pointable);
981 // Player can dig these
982 getboolfield(L, index, "diggable", f.diggable);
983 // Player can climb these
984 getboolfield(L, index, "climbable", f.climbable);
985 // Player can build on these
986 getboolfield(L, index, "buildable_to", f.buildable_to);
987 // Metadata name of node (eg. "furnace")
988 getstringfield(L, index, "metadata_name", f.metadata_name);
989 // Whether the node is non-liquid, source liquid or flowing liquid
990 f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
991 es_LiquidType, LIQUID_NONE);
992 // If the content is liquid, this is the flowing version of the liquid.
993 getstringfield(L, index, "liquid_alternative_flowing",
994 f.liquid_alternative_flowing);
995 // If the content is liquid, this is the source version of the liquid.
996 getstringfield(L, index, "liquid_alternative_source",
997 f.liquid_alternative_source);
998 // Viscosity for fluid flow, ranging from 1 to 7, with
999 // 1 giving almost instantaneous propagation and 7 being
1000 // the slowest possible
1001 f.liquid_viscosity = getintfield_default(L, index,
1002 "liquid_viscosity", f.liquid_viscosity);
1003 // Amount of light the node emits
1004 f.light_source = getintfield_default(L, index,
1005 "light_source", f.light_source);
1006 f.damage_per_second = getintfield_default(L, index,
1007 "damage_per_second", f.damage_per_second);
1009 lua_getfield(L, index, "selection_box");
1010 if(lua_istable(L, -1)){
1011 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
1012 es_NodeBoxType, NODEBOX_REGULAR);
1014 lua_getfield(L, -1, "fixed");
1015 if(lua_istable(L, -1))
1016 f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
1019 lua_getfield(L, -1, "wall_top");
1020 if(lua_istable(L, -1))
1021 f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
1024 lua_getfield(L, -1, "wall_bottom");
1025 if(lua_istable(L, -1))
1026 f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
1029 lua_getfield(L, -1, "wall_side");
1030 if(lua_istable(L, -1))
1031 f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
1036 // Set to true if paramtype used to be 'facedir_simple'
1037 getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
1038 // Set to true if wall_mounted used to be set to true
1039 getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
1048 static ItemStack read_item(lua_State *L, int index);
1050 static void inventory_set_list_from_lua(Inventory *inv, const char *name,
1051 lua_State *L, int tableindex, int forcesize=-1)
1053 dstream<<"inventory_set_list_from_lua\n";
1055 tableindex = lua_gettop(L) + 1 + tableindex;
1056 // If nil, delete list
1057 if(lua_isnil(L, tableindex)){
1058 inv->deleteList(name);
1061 // Otherwise set list
1062 std::vector<ItemStack> items;
1063 luaL_checktype(L, tableindex, LUA_TTABLE);
1065 while(lua_next(L, tableindex) != 0){
1066 // key at index -2 and value at index -1
1067 items.push_back(read_item(L, -1));
1068 // removes value, keeps key for next iteration
1071 int listsize = (forcesize != -1) ? forcesize : items.size();
1072 InventoryList *invlist = inv->addList(name, listsize);
1074 for(std::vector<ItemStack>::const_iterator
1075 i = items.begin(); i != items.end(); i++){
1076 if(forcesize != -1 && index == forcesize)
1078 invlist->changeItem(index, *i);
1081 while(forcesize != -1 && index < forcesize){
1082 invlist->deleteItem(index);
1085 dstream<<"inventory_set_list_from_lua done\n";
1088 static void inventory_get_list_to_lua(Inventory *inv, const char *name,
1091 InventoryList *invlist = inv->getList(name);
1092 if(invlist == NULL){
1096 // Get the table insert function
1097 lua_getglobal(L, "table");
1098 lua_getfield(L, -1, "insert");
1099 int table_insert = lua_gettop(L);
1100 // Create and fill table
1102 int table = lua_gettop(L);
1103 for(u32 i=0; i<invlist->getSize(); i++){
1104 ItemStack item = invlist->getItem(i);
1105 lua_pushvalue(L, table_insert);
1106 lua_pushvalue(L, table);
1107 lua_pushstring(L, item.getItemString().c_str());
1108 if(lua_pcall(L, 2, 0, 0))
1109 script_error(L, "error: %s", lua_tostring(L, -1));
1114 Helpful macros for userdata classes
1117 #define method(class, name) {#name, class::l_##name}
1128 static const char className[];
1129 static const luaL_reg methods[];
1131 // Exported functions
1133 // garbage collector
1134 static int gc_object(lua_State *L)
1136 LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1));
1141 // is_empty(self) -> true/false
1142 static int l_is_empty(lua_State *L)
1144 LuaItemStack *o = checkobject(L, 1);
1145 ItemStack &item = o->m_stack;
1146 lua_pushboolean(L, item.empty());
1150 // get_name(self) -> string
1151 static int l_get_name(lua_State *L)
1153 LuaItemStack *o = checkobject(L, 1);
1154 ItemStack &item = o->m_stack;
1155 lua_pushstring(L, item.name.c_str());
1159 // get_count(self) -> number
1160 static int l_get_count(lua_State *L)
1162 LuaItemStack *o = checkobject(L, 1);
1163 ItemStack &item = o->m_stack;
1164 lua_pushinteger(L, item.count);
1168 // get_wear(self) -> number
1169 static int l_get_wear(lua_State *L)
1171 LuaItemStack *o = checkobject(L, 1);
1172 ItemStack &item = o->m_stack;
1173 lua_pushinteger(L, item.wear);
1177 // get_metadata(self) -> string
1178 static int l_get_metadata(lua_State *L)
1180 LuaItemStack *o = checkobject(L, 1);
1181 ItemStack &item = o->m_stack;
1182 lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
1186 // clear(self) -> true
1187 static int l_clear(lua_State *L)
1189 LuaItemStack *o = checkobject(L, 1);
1191 lua_pushboolean(L, true);
1195 // replace(self, itemstack or itemstring or table or nil) -> true
1196 static int l_replace(lua_State *L)
1198 LuaItemStack *o = checkobject(L, 1);
1199 o->m_stack = read_item(L, 2);
1200 lua_pushboolean(L, true);
1204 // to_string(self) -> string
1205 static int l_to_string(lua_State *L)
1207 LuaItemStack *o = checkobject(L, 1);
1208 std::string itemstring = o->m_stack.getItemString();
1209 lua_pushstring(L, itemstring.c_str());
1213 // to_table(self) -> table or nil
1214 static int l_to_table(lua_State *L)
1216 LuaItemStack *o = checkobject(L, 1);
1217 const ItemStack &item = o->m_stack;
1225 lua_pushstring(L, item.name.c_str());
1226 lua_setfield(L, -2, "name");
1227 lua_pushinteger(L, item.count);
1228 lua_setfield(L, -2, "count");
1229 lua_pushinteger(L, item.wear);
1230 lua_setfield(L, -2, "wear");
1231 lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
1232 lua_setfield(L, -2, "metadata");
1237 // get_stack_max(self) -> number
1238 static int l_get_stack_max(lua_State *L)
1240 LuaItemStack *o = checkobject(L, 1);
1241 ItemStack &item = o->m_stack;
1242 lua_pushinteger(L, item.getStackMax(get_server(L)->idef()));
1246 // get_free_space(self) -> number
1247 static int l_get_free_space(lua_State *L)
1249 LuaItemStack *o = checkobject(L, 1);
1250 ItemStack &item = o->m_stack;
1251 lua_pushinteger(L, item.freeSpace(get_server(L)->idef()));
1255 // is_known(self) -> true/false
1256 // Checks if the item is defined.
1257 static int l_is_known(lua_State *L)
1259 LuaItemStack *o = checkobject(L, 1);
1260 ItemStack &item = o->m_stack;
1261 bool is_known = item.isKnown(get_server(L)->idef());
1262 lua_pushboolean(L, is_known);
1266 // get_definition(self) -> table
1267 // Returns the item definition table from minetest.registered_items,
1268 // or a fallback one (name="unknown")
1269 static int l_get_definition(lua_State *L)
1271 LuaItemStack *o = checkobject(L, 1);
1272 ItemStack &item = o->m_stack;
1274 // Get minetest.registered_items[name]
1275 lua_getglobal(L, "minetest");
1276 lua_getfield(L, -1, "registered_items");
1277 luaL_checktype(L, -1, LUA_TTABLE);
1278 lua_getfield(L, -1, item.name.c_str());
1279 if(lua_isnil(L, -1))
1282 lua_getfield(L, -1, "unknown");
1287 // get_tool_capabilities(self) -> table
1288 // Returns the effective tool digging properties.
1289 // Returns those of the hand ("") if this item has none associated.
1290 static int l_get_tool_capabilities(lua_State *L)
1292 LuaItemStack *o = checkobject(L, 1);
1293 ItemStack &item = o->m_stack;
1294 const ToolCapabilities &prop =
1295 item.getToolCapabilities(get_server(L)->idef());
1296 push_tool_capabilities(L, prop);
1300 // add_wear(self, amount) -> true/false
1301 // The range for "amount" is [0,65535]. Wear is only added if the item
1302 // is a tool. Adding wear might destroy the item.
1303 // Returns true if the item is (or was) a tool.
1304 static int l_add_wear(lua_State *L)
1306 LuaItemStack *o = checkobject(L, 1);
1307 ItemStack &item = o->m_stack;
1308 int amount = lua_tointeger(L, 2);
1309 bool result = item.addWear(amount, get_server(L)->idef());
1310 lua_pushboolean(L, result);
1314 // add_item(self, itemstack or itemstring or table or nil) -> itemstack
1315 // Returns leftover item stack
1316 static int l_add_item(lua_State *L)
1318 LuaItemStack *o = checkobject(L, 1);
1319 ItemStack &item = o->m_stack;
1320 ItemStack newitem = read_item(L, 2);
1321 ItemStack leftover = item.addItem(newitem, get_server(L)->idef());
1322 create(L, leftover);
1326 // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
1327 // First return value is true iff the new item fits fully into the stack
1328 // Second return value is the would-be-left-over item stack
1329 static int l_item_fits(lua_State *L)
1331 LuaItemStack *o = checkobject(L, 1);
1332 ItemStack &item = o->m_stack;
1333 ItemStack newitem = read_item(L, 2);
1335 bool fits = item.itemFits(newitem, &restitem, get_server(L)->idef());
1336 lua_pushboolean(L, fits); // first return value
1337 create(L, restitem); // second return value
1341 // take_item(self, takecount=1) -> itemstack
1342 static int l_take_item(lua_State *L)
1344 LuaItemStack *o = checkobject(L, 1);
1345 ItemStack &item = o->m_stack;
1347 if(!lua_isnone(L, 2))
1348 takecount = lua_tointeger(L, 2);
1349 ItemStack taken = item.takeItem(takecount);
1354 // peek_item(self, peekcount=1) -> itemstack
1355 static int l_peek_item(lua_State *L)
1357 LuaItemStack *o = checkobject(L, 1);
1358 ItemStack &item = o->m_stack;
1360 if(!lua_isnone(L, 2))
1361 peekcount = lua_tointeger(L, 2);
1362 ItemStack peekaboo = item.peekItem(peekcount);
1363 create(L, peekaboo);
1368 LuaItemStack(const ItemStack &item):
1377 const ItemStack& getItem() const
1381 ItemStack& getItem()
1386 // LuaItemStack(itemstack or itemstring or table or nil)
1387 // Creates an LuaItemStack and leaves it on top of stack
1388 static int create_object(lua_State *L)
1390 ItemStack item = read_item(L, 1);
1391 LuaItemStack *o = new LuaItemStack(item);
1392 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1393 luaL_getmetatable(L, className);
1394 lua_setmetatable(L, -2);
1397 // Not callable from Lua
1398 static int create(lua_State *L, const ItemStack &item)
1400 LuaItemStack *o = new LuaItemStack(item);
1401 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1402 luaL_getmetatable(L, className);
1403 lua_setmetatable(L, -2);
1407 static LuaItemStack* checkobject(lua_State *L, int narg)
1409 luaL_checktype(L, narg, LUA_TUSERDATA);
1410 void *ud = luaL_checkudata(L, narg, className);
1411 if(!ud) luaL_typerror(L, narg, className);
1412 return *(LuaItemStack**)ud; // unbox pointer
1415 static void Register(lua_State *L)
1418 int methodtable = lua_gettop(L);
1419 luaL_newmetatable(L, className);
1420 int metatable = lua_gettop(L);
1422 lua_pushliteral(L, "__metatable");
1423 lua_pushvalue(L, methodtable);
1424 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1426 lua_pushliteral(L, "__index");
1427 lua_pushvalue(L, methodtable);
1428 lua_settable(L, metatable);
1430 lua_pushliteral(L, "__gc");
1431 lua_pushcfunction(L, gc_object);
1432 lua_settable(L, metatable);
1434 lua_pop(L, 1); // drop metatable
1436 luaL_openlib(L, 0, methods, 0); // fill methodtable
1437 lua_pop(L, 1); // drop methodtable
1439 // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
1440 lua_register(L, className, create_object);
1443 const char LuaItemStack::className[] = "ItemStack";
1444 const luaL_reg LuaItemStack::methods[] = {
1445 method(LuaItemStack, is_empty),
1446 method(LuaItemStack, get_name),
1447 method(LuaItemStack, get_count),
1448 method(LuaItemStack, get_wear),
1449 method(LuaItemStack, get_metadata),
1450 method(LuaItemStack, clear),
1451 method(LuaItemStack, replace),
1452 method(LuaItemStack, to_string),
1453 method(LuaItemStack, to_table),
1454 method(LuaItemStack, get_stack_max),
1455 method(LuaItemStack, get_free_space),
1456 method(LuaItemStack, is_known),
1457 method(LuaItemStack, get_definition),
1458 method(LuaItemStack, get_tool_capabilities),
1459 method(LuaItemStack, add_wear),
1460 method(LuaItemStack, add_item),
1461 method(LuaItemStack, item_fits),
1462 method(LuaItemStack, take_item),
1463 method(LuaItemStack, peek_item),
1467 static ItemStack read_item(lua_State *L, int index)
1470 index = lua_gettop(L) + 1 + index;
1472 if(lua_isnil(L, index))
1476 else if(lua_isuserdata(L, index))
1478 // Convert from LuaItemStack
1479 LuaItemStack *o = LuaItemStack::checkobject(L, index);
1480 return o->getItem();
1482 else if(lua_isstring(L, index))
1484 // Convert from itemstring
1485 std::string itemstring = lua_tostring(L, index);
1486 IItemDefManager *idef = get_server(L)->idef();
1490 item.deSerialize(itemstring, idef);
1493 catch(SerializationError &e)
1495 infostream<<"WARNING: unable to create item from itemstring"
1496 <<": "<<itemstring<<std::endl;
1500 else if(lua_istable(L, index))
1502 // Convert from table
1503 IItemDefManager *idef = get_server(L)->idef();
1504 std::string name = getstringfield_default(L, index, "name", "");
1505 int count = getintfield_default(L, index, "count", 1);
1506 int wear = getintfield_default(L, index, "wear", 0);
1507 std::string metadata = getstringfield_default(L, index, "metadata", "");
1508 return ItemStack(name, count, wear, metadata, idef);
1512 throw LuaError(L, "Expecting itemstack, itemstring, table or nil");
1523 InventoryLocation m_loc;
1525 static const char className[];
1526 static const luaL_reg methods[];
1528 static InvRef *checkobject(lua_State *L, int narg)
1530 luaL_checktype(L, narg, LUA_TUSERDATA);
1531 void *ud = luaL_checkudata(L, narg, className);
1532 if(!ud) luaL_typerror(L, narg, className);
1533 return *(InvRef**)ud; // unbox pointer
1536 static Inventory* getinv(lua_State *L, InvRef *ref)
1538 return get_server(L)->getInventory(ref->m_loc);
1541 static InventoryList* getlist(lua_State *L, InvRef *ref,
1542 const char *listname)
1544 Inventory *inv = getinv(L, ref);
1547 return inv->getList(listname);
1550 static void reportInventoryChange(lua_State *L, InvRef *ref)
1552 // Inform other things that the inventory has changed
1553 get_server(L)->setInventoryModified(ref->m_loc);
1556 // Exported functions
1558 // garbage collector
1559 static int gc_object(lua_State *L) {
1560 InvRef *o = *(InvRef **)(lua_touserdata(L, 1));
1565 // get_size(self, listname)
1566 static int l_get_size(lua_State *L)
1568 InvRef *ref = checkobject(L, 1);
1569 const char *listname = luaL_checkstring(L, 2);
1570 InventoryList *list = getlist(L, ref, listname);
1572 lua_pushinteger(L, list->getSize());
1574 lua_pushinteger(L, 0);
1579 // set_size(self, listname, size)
1580 static int l_set_size(lua_State *L)
1582 InvRef *ref = checkobject(L, 1);
1583 const char *listname = luaL_checkstring(L, 2);
1584 int newsize = luaL_checknumber(L, 3);
1585 Inventory *inv = getinv(L, ref);
1587 inv->deleteList(listname);
1588 reportInventoryChange(L, ref);
1591 InventoryList *list = inv->getList(listname);
1593 list->setSize(newsize);
1595 list = inv->addList(listname, newsize);
1597 reportInventoryChange(L, ref);
1601 // get_stack(self, listname, i) -> itemstack
1602 static int l_get_stack(lua_State *L)
1604 InvRef *ref = checkobject(L, 1);
1605 const char *listname = luaL_checkstring(L, 2);
1606 int i = luaL_checknumber(L, 3) - 1;
1607 InventoryList *list = getlist(L, ref, listname);
1609 if(list != NULL && i >= 0 && i < (int) list->getSize())
1610 item = list->getItem(i);
1611 LuaItemStack::create(L, item);
1615 // set_stack(self, listname, i, stack) -> true/false
1616 static int l_set_stack(lua_State *L)
1618 InvRef *ref = checkobject(L, 1);
1619 const char *listname = luaL_checkstring(L, 2);
1620 int i = luaL_checknumber(L, 3) - 1;
1621 ItemStack newitem = read_item(L, 4);
1622 InventoryList *list = getlist(L, ref, listname);
1623 if(list != NULL && i >= 0 && i < (int) list->getSize()){
1624 list->changeItem(i, newitem);
1625 reportInventoryChange(L, ref);
1626 lua_pushboolean(L, true);
1628 lua_pushboolean(L, false);
1633 // get_list(self, listname) -> list or nil
1634 static int l_get_list(lua_State *L)
1636 InvRef *ref = checkobject(L, 1);
1637 const char *listname = luaL_checkstring(L, 2);
1638 Inventory *inv = getinv(L, ref);
1639 inventory_get_list_to_lua(inv, listname, L);
1643 // set_list(self, listname, list)
1644 static int l_set_list(lua_State *L)
1646 InvRef *ref = checkobject(L, 1);
1647 const char *listname = luaL_checkstring(L, 2);
1648 Inventory *inv = getinv(L, ref);
1649 InventoryList *list = inv->getList(listname);
1651 inventory_set_list_from_lua(inv, listname, L, 3,
1654 inventory_set_list_from_lua(inv, listname, L, 3);
1655 reportInventoryChange(L, ref);
1659 // add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
1660 // Returns the leftover stack
1661 static int l_add_item(lua_State *L)
1663 InvRef *ref = checkobject(L, 1);
1664 const char *listname = luaL_checkstring(L, 2);
1665 ItemStack item = read_item(L, 3);
1666 InventoryList *list = getlist(L, ref, listname);
1668 ItemStack leftover = list->addItem(item);
1669 if(leftover.count != item.count)
1670 reportInventoryChange(L, ref);
1671 LuaItemStack::create(L, leftover);
1673 LuaItemStack::create(L, item);
1678 // room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false
1679 // Returns true if the item completely fits into the list
1680 static int l_room_for_item(lua_State *L)
1682 InvRef *ref = checkobject(L, 1);
1683 const char *listname = luaL_checkstring(L, 2);
1684 ItemStack item = read_item(L, 3);
1685 InventoryList *list = getlist(L, ref, listname);
1687 lua_pushboolean(L, list->roomForItem(item));
1689 lua_pushboolean(L, false);
1694 // contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false
1695 // Returns true if the list contains the given count of the given item name
1696 static int l_contains_item(lua_State *L)
1698 InvRef *ref = checkobject(L, 1);
1699 const char *listname = luaL_checkstring(L, 2);
1700 ItemStack item = read_item(L, 3);
1701 InventoryList *list = getlist(L, ref, listname);
1703 lua_pushboolean(L, list->containsItem(item));
1705 lua_pushboolean(L, false);
1710 // remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
1711 // Returns the items that were actually removed
1712 static int l_remove_item(lua_State *L)
1714 InvRef *ref = checkobject(L, 1);
1715 const char *listname = luaL_checkstring(L, 2);
1716 ItemStack item = read_item(L, 3);
1717 InventoryList *list = getlist(L, ref, listname);
1719 ItemStack removed = list->removeItem(item);
1720 if(!removed.empty())
1721 reportInventoryChange(L, ref);
1722 LuaItemStack::create(L, removed);
1724 LuaItemStack::create(L, ItemStack());
1730 InvRef(const InventoryLocation &loc):
1739 // Creates an InvRef and leaves it on top of stack
1740 // Not callable from Lua; all references are created on the C side.
1741 static void create(lua_State *L, const InventoryLocation &loc)
1743 InvRef *o = new InvRef(loc);
1744 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1745 luaL_getmetatable(L, className);
1746 lua_setmetatable(L, -2);
1748 static void createPlayer(lua_State *L, Player *player)
1750 InventoryLocation loc;
1751 loc.setPlayer(player->getName());
1754 static void createNodeMeta(lua_State *L, v3s16 p)
1756 InventoryLocation loc;
1761 static void Register(lua_State *L)
1764 int methodtable = lua_gettop(L);
1765 luaL_newmetatable(L, className);
1766 int metatable = lua_gettop(L);
1768 lua_pushliteral(L, "__metatable");
1769 lua_pushvalue(L, methodtable);
1770 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1772 lua_pushliteral(L, "__index");
1773 lua_pushvalue(L, methodtable);
1774 lua_settable(L, metatable);
1776 lua_pushliteral(L, "__gc");
1777 lua_pushcfunction(L, gc_object);
1778 lua_settable(L, metatable);
1780 lua_pop(L, 1); // drop metatable
1782 luaL_openlib(L, 0, methods, 0); // fill methodtable
1783 lua_pop(L, 1); // drop methodtable
1785 // Cannot be created from Lua
1786 //lua_register(L, className, create_object);
1789 const char InvRef::className[] = "InvRef";
1790 const luaL_reg InvRef::methods[] = {
1791 method(InvRef, get_size),
1792 method(InvRef, set_size),
1793 method(InvRef, get_stack),
1794 method(InvRef, set_stack),
1795 method(InvRef, get_list),
1796 method(InvRef, set_list),
1797 method(InvRef, add_item),
1798 method(InvRef, room_for_item),
1799 method(InvRef, contains_item),
1800 method(InvRef, remove_item),
1812 ServerEnvironment *m_env;
1814 static const char className[];
1815 static const luaL_reg methods[];
1817 static NodeMetaRef *checkobject(lua_State *L, int narg)
1819 luaL_checktype(L, narg, LUA_TUSERDATA);
1820 void *ud = luaL_checkudata(L, narg, className);
1821 if(!ud) luaL_typerror(L, narg, className);
1822 return *(NodeMetaRef**)ud; // unbox pointer
1825 static NodeMetadata* getmeta(NodeMetaRef *ref)
1827 NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
1831 /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
1833 NodeMetadata *meta = getmeta(ref);
1836 if(meta->typeId() != NODEMETA_GENERIC)
1838 return (IGenericNodeMetadata*)meta;
1841 static void reportMetadataChange(NodeMetaRef *ref)
1843 // Inform other things that the metadata has changed
1844 v3s16 blockpos = getNodeBlockPos(ref->m_p);
1846 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1848 ref->m_env->getMap().dispatchEvent(&event);
1849 // Set the block to be saved
1850 MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
1852 block->raiseModified(MOD_STATE_WRITE_NEEDED,
1853 "NodeMetaRef::reportMetadataChange");
1856 // Exported functions
1858 // garbage collector
1859 static int gc_object(lua_State *L) {
1860 NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
1866 static int l_get_type(lua_State *L)
1868 NodeMetaRef *ref = checkobject(L, 1);
1869 NodeMetadata *meta = getmeta(ref);
1875 lua_pushstring(L, meta->typeName());
1879 // allows_text_input(self)
1880 static int l_allows_text_input(lua_State *L)
1882 NodeMetaRef *ref = checkobject(L, 1);
1883 NodeMetadata *meta = getmeta(ref);
1884 if(meta == NULL) return 0;
1886 lua_pushboolean(L, meta->allowsTextInput());
1890 // set_text(self, text)
1891 static int l_set_text(lua_State *L)
1893 NodeMetaRef *ref = checkobject(L, 1);
1894 NodeMetadata *meta = getmeta(ref);
1895 if(meta == NULL) return 0;
1897 std::string text = luaL_checkstring(L, 2);
1898 meta->setText(text);
1899 reportMetadataChange(ref);
1904 static int l_get_text(lua_State *L)
1906 NodeMetaRef *ref = checkobject(L, 1);
1907 NodeMetadata *meta = getmeta(ref);
1908 if(meta == NULL) return 0;
1910 std::string text = meta->getText();
1911 lua_pushstring(L, text.c_str());
1916 static int l_get_owner(lua_State *L)
1918 NodeMetaRef *ref = checkobject(L, 1);
1919 NodeMetadata *meta = getmeta(ref);
1920 if(meta == NULL) return 0;
1922 std::string owner = meta->getOwner();
1923 lua_pushstring(L, owner.c_str());
1927 // set_owner(self, string)
1928 static int l_set_owner(lua_State *L)
1930 NodeMetaRef *ref = checkobject(L, 1);
1931 NodeMetadata *meta = getmeta(ref);
1932 if(meta == NULL) return 0;
1934 std::string owner = luaL_checkstring(L, 2);
1935 meta->setOwner(owner);
1936 reportMetadataChange(ref);
1940 // get_allow_removal(self)
1941 static int l_get_allow_removal(lua_State *L)
1943 NodeMetaRef *ref = checkobject(L, 1);
1944 NodeMetadata *meta = getmeta(ref);
1946 lua_pushboolean(L, true);
1950 lua_pushboolean(L, !meta->nodeRemovalDisabled());
1954 /* IGenericNodeMetadata interface */
1956 // set_infotext(self, text)
1957 static int l_set_infotext(lua_State *L)
1959 NodeMetaRef *ref = checkobject(L, 1);
1960 NodeMetadata *meta = getmeta(ref);
1961 if(meta == NULL) return 0;
1963 std::string text = luaL_checkstring(L, 2);
1964 meta->setInfoText(text);
1965 reportMetadataChange(ref);
1969 // get_inventory(self)
1970 static int l_get_inventory(lua_State *L)
1972 NodeMetaRef *ref = checkobject(L, 1);
1973 NodeMetadata *meta = getmeta(ref);
1974 if(meta == NULL) return 0;
1976 InvRef::createNodeMeta(L, ref->m_p);
1980 // set_inventory_draw_spec(self, text)
1981 static int l_set_inventory_draw_spec(lua_State *L)
1983 NodeMetaRef *ref = checkobject(L, 1);
1984 NodeMetadata *meta = getmeta(ref);
1985 if(meta == NULL) return 0;
1987 std::string text = luaL_checkstring(L, 2);
1988 meta->setInventoryDrawSpec(text);
1989 reportMetadataChange(ref);
1993 // set_allow_text_input(self, text)
1994 static int l_set_allow_text_input(lua_State *L)
1996 NodeMetaRef *ref = checkobject(L, 1);
1997 NodeMetadata *meta = getmeta(ref);
1998 if(meta == NULL) return 0;
2000 bool b = lua_toboolean(L, 2);
2001 meta->setAllowTextInput(b);
2002 reportMetadataChange(ref);
2006 // set_allow_removal(self, text)
2007 static int l_set_allow_removal(lua_State *L)
2009 NodeMetaRef *ref = checkobject(L, 1);
2010 NodeMetadata *meta = getmeta(ref);
2011 if(meta == NULL) return 0;
2013 bool b = lua_toboolean(L, 2);
2014 meta->setRemovalDisabled(!b);
2015 reportMetadataChange(ref);
2019 // set_enforce_owner(self, text)
2020 static int l_set_enforce_owner(lua_State *L)
2022 NodeMetaRef *ref = checkobject(L, 1);
2023 NodeMetadata *meta = getmeta(ref);
2024 if(meta == NULL) return 0;
2026 bool b = lua_toboolean(L, 2);
2027 meta->setEnforceOwner(b);
2028 reportMetadataChange(ref);
2032 // is_inventory_modified(self)
2033 static int l_is_inventory_modified(lua_State *L)
2035 NodeMetaRef *ref = checkobject(L, 1);
2036 NodeMetadata *meta = getmeta(ref);
2037 if(meta == NULL) return 0;
2039 lua_pushboolean(L, meta->isInventoryModified());
2043 // reset_inventory_modified(self)
2044 static int l_reset_inventory_modified(lua_State *L)
2046 NodeMetaRef *ref = checkobject(L, 1);
2047 NodeMetadata *meta = getmeta(ref);
2048 if(meta == NULL) return 0;
2050 meta->resetInventoryModified();
2051 reportMetadataChange(ref);
2055 // is_text_modified(self)
2056 static int l_is_text_modified(lua_State *L)
2058 NodeMetaRef *ref = checkobject(L, 1);
2059 NodeMetadata *meta = getmeta(ref);
2060 if(meta == NULL) return 0;
2062 lua_pushboolean(L, meta->isTextModified());
2066 // reset_text_modified(self)
2067 static int l_reset_text_modified(lua_State *L)
2069 NodeMetaRef *ref = checkobject(L, 1);
2070 NodeMetadata *meta = getmeta(ref);
2071 if(meta == NULL) return 0;
2073 meta->resetTextModified();
2074 reportMetadataChange(ref);
2078 // set_string(self, name, var)
2079 static int l_set_string(lua_State *L)
2081 NodeMetaRef *ref = checkobject(L, 1);
2082 NodeMetadata *meta = getmeta(ref);
2083 if(meta == NULL) return 0;
2085 std::string name = luaL_checkstring(L, 2);
2087 const char *s = lua_tolstring(L, 3, &len);
2088 std::string str(s, len);
2089 meta->setString(name, str);
2090 reportMetadataChange(ref);
2094 // get_string(self, name)
2095 static int l_get_string(lua_State *L)
2097 NodeMetaRef *ref = checkobject(L, 1);
2098 NodeMetadata *meta = getmeta(ref);
2099 if(meta == NULL) return 0;
2101 std::string name = luaL_checkstring(L, 2);
2102 std::string str = meta->getString(name);
2103 lua_pushlstring(L, str.c_str(), str.size());
2108 NodeMetaRef(v3s16 p, ServerEnvironment *env):
2118 // Creates an NodeMetaRef and leaves it on top of stack
2119 // Not callable from Lua; all references are created on the C side.
2120 static void create(lua_State *L, v3s16 p, ServerEnvironment *env)
2122 NodeMetaRef *o = new NodeMetaRef(p, env);
2123 //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
2124 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2125 luaL_getmetatable(L, className);
2126 lua_setmetatable(L, -2);
2129 static void Register(lua_State *L)
2132 int methodtable = lua_gettop(L);
2133 luaL_newmetatable(L, className);
2134 int metatable = lua_gettop(L);
2136 lua_pushliteral(L, "__metatable");
2137 lua_pushvalue(L, methodtable);
2138 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2140 lua_pushliteral(L, "__index");
2141 lua_pushvalue(L, methodtable);
2142 lua_settable(L, metatable);
2144 lua_pushliteral(L, "__gc");
2145 lua_pushcfunction(L, gc_object);
2146 lua_settable(L, metatable);
2148 lua_pop(L, 1); // drop metatable
2150 luaL_openlib(L, 0, methods, 0); // fill methodtable
2151 lua_pop(L, 1); // drop methodtable
2153 // Cannot be created from Lua
2154 //lua_register(L, className, create_object);
2157 const char NodeMetaRef::className[] = "NodeMetaRef";
2158 const luaL_reg NodeMetaRef::methods[] = {
2159 method(NodeMetaRef, get_type),
2160 method(NodeMetaRef, allows_text_input),
2161 method(NodeMetaRef, set_text),
2162 method(NodeMetaRef, get_text),
2163 method(NodeMetaRef, get_owner),
2164 method(NodeMetaRef, set_owner),
2165 method(NodeMetaRef, get_allow_removal),
2166 method(NodeMetaRef, set_infotext),
2167 method(NodeMetaRef, get_inventory),
2168 method(NodeMetaRef, set_inventory_draw_spec),
2169 method(NodeMetaRef, set_allow_text_input),
2170 method(NodeMetaRef, set_allow_removal),
2171 method(NodeMetaRef, set_enforce_owner),
2172 method(NodeMetaRef, is_inventory_modified),
2173 method(NodeMetaRef, reset_inventory_modified),
2174 method(NodeMetaRef, is_text_modified),
2175 method(NodeMetaRef, reset_text_modified),
2176 method(NodeMetaRef, set_string),
2177 method(NodeMetaRef, get_string),
2188 ServerActiveObject *m_object;
2190 static const char className[];
2191 static const luaL_reg methods[];
2193 static ObjectRef *checkobject(lua_State *L, int narg)
2195 luaL_checktype(L, narg, LUA_TUSERDATA);
2196 void *ud = luaL_checkudata(L, narg, className);
2197 if(!ud) luaL_typerror(L, narg, className);
2198 return *(ObjectRef**)ud; // unbox pointer
2201 static ServerActiveObject* getobject(ObjectRef *ref)
2203 ServerActiveObject *co = ref->m_object;
2207 static LuaEntitySAO* getluaobject(ObjectRef *ref)
2209 ServerActiveObject *obj = getobject(ref);
2212 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
2214 return (LuaEntitySAO*)obj;
2217 static ServerRemotePlayer* getplayer(ObjectRef *ref)
2219 ServerActiveObject *obj = getobject(ref);
2222 if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
2224 return static_cast<ServerRemotePlayer*>(obj);
2227 // Exported functions
2229 // garbage collector
2230 static int gc_object(lua_State *L) {
2231 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
2232 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
2238 static int l_remove(lua_State *L)
2240 ObjectRef *ref = checkobject(L, 1);
2241 ServerActiveObject *co = getobject(ref);
2242 if(co == NULL) return 0;
2243 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
2244 co->m_removed = true;
2249 // returns: {x=num, y=num, z=num}
2250 static int l_getpos(lua_State *L)
2252 ObjectRef *ref = checkobject(L, 1);
2253 ServerActiveObject *co = getobject(ref);
2254 if(co == NULL) return 0;
2255 v3f pos = co->getBasePosition() / BS;
2257 lua_pushnumber(L, pos.X);
2258 lua_setfield(L, -2, "x");
2259 lua_pushnumber(L, pos.Y);
2260 lua_setfield(L, -2, "y");
2261 lua_pushnumber(L, pos.Z);
2262 lua_setfield(L, -2, "z");
2266 // setpos(self, pos)
2267 static int l_setpos(lua_State *L)
2269 ObjectRef *ref = checkobject(L, 1);
2270 //LuaEntitySAO *co = getluaobject(ref);
2271 ServerActiveObject *co = getobject(ref);
2272 if(co == NULL) return 0;
2274 v3f pos = checkFloatPos(L, 2);
2277 // Move player if applicable
2278 ServerRemotePlayer *player = getplayer(ref);
2280 get_server(L)->SendMovePlayer(player);
2284 // moveto(self, pos, continuous=false)
2285 static int l_moveto(lua_State *L)
2287 ObjectRef *ref = checkobject(L, 1);
2288 //LuaEntitySAO *co = getluaobject(ref);
2289 ServerActiveObject *co = getobject(ref);
2290 if(co == NULL) return 0;
2292 v3f pos = checkFloatPos(L, 2);
2294 bool continuous = lua_toboolean(L, 3);
2296 co->moveTo(pos, continuous);
2300 // punch(self, puncher); puncher = an another ObjectRef
2301 static int l_punch(lua_State *L)
2303 ObjectRef *ref = checkobject(L, 1);
2304 ObjectRef *ref2 = checkobject(L, 2);
2305 ServerActiveObject *co = getobject(ref);
2306 ServerActiveObject *co2 = getobject(ref2);
2307 if(co == NULL) return 0;
2308 if(co2 == NULL) return 0;
2314 // right_click(self, clicker); clicker = an another ObjectRef
2315 static int l_right_click(lua_State *L)
2317 ObjectRef *ref = checkobject(L, 1);
2318 ObjectRef *ref2 = checkobject(L, 2);
2319 ServerActiveObject *co = getobject(ref);
2320 ServerActiveObject *co2 = getobject(ref2);
2321 if(co == NULL) return 0;
2322 if(co2 == NULL) return 0;
2324 co->rightClick(co2);
2329 // hp = number of hitpoints (2 * number of hearts)
2331 static int l_set_hp(lua_State *L)
2333 ObjectRef *ref = checkobject(L, 1);
2334 luaL_checknumber(L, 2);
2335 ServerActiveObject *co = getobject(ref);
2336 if(co == NULL) return 0;
2337 int hp = lua_tonumber(L, 2);
2338 infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
2339 <<" hp="<<hp<<std::endl;
2347 // returns: number of hitpoints (2 * number of hearts)
2348 // 0 if not applicable to this type of object
2349 static int l_get_hp(lua_State *L)
2351 ObjectRef *ref = checkobject(L, 1);
2352 ServerActiveObject *co = getobject(ref);
2353 if(co == NULL) return 0;
2354 int hp = co->getHP();
2355 infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
2356 <<" hp="<<hp<<std::endl;
2358 lua_pushnumber(L, hp);
2362 // get_inventory(self)
2363 static int l_get_inventory(lua_State *L)
2365 ObjectRef *ref = checkobject(L, 1);
2366 ServerActiveObject *co = getobject(ref);
2367 if(co == NULL) return 0;
2369 InventoryLocation loc = co->getInventoryLocation();
2370 if(get_server(L)->getInventory(loc) != NULL)
2371 InvRef::create(L, loc);
2377 // get_wield_list(self)
2378 static int l_get_wield_list(lua_State *L)
2380 ObjectRef *ref = checkobject(L, 1);
2381 ServerActiveObject *co = getobject(ref);
2382 if(co == NULL) return 0;
2384 lua_pushstring(L, co->getWieldList().c_str());
2388 // get_wield_index(self)
2389 static int l_get_wield_index(lua_State *L)
2391 ObjectRef *ref = checkobject(L, 1);
2392 ServerActiveObject *co = getobject(ref);
2393 if(co == NULL) return 0;
2395 lua_pushinteger(L, co->getWieldIndex() + 1);
2399 // get_wielded_item(self)
2400 static int l_get_wielded_item(lua_State *L)
2402 ObjectRef *ref = checkobject(L, 1);
2403 ServerActiveObject *co = getobject(ref);
2404 if(co == NULL) return 0;
2406 LuaItemStack::create(L, co->getWieldedItem());
2410 // set_wielded_item(self, itemstack or itemstring or table or nil)
2411 static int l_set_wielded_item(lua_State *L)
2413 ObjectRef *ref = checkobject(L, 1);
2414 ServerActiveObject *co = getobject(ref);
2415 if(co == NULL) return 0;
2417 ItemStack item = read_item(L, 2);
2418 bool success = co->setWieldedItem(item);
2419 lua_pushboolean(L, success);
2423 /* LuaEntitySAO-only */
2425 // setvelocity(self, {x=num, y=num, z=num})
2426 static int l_setvelocity(lua_State *L)
2428 ObjectRef *ref = checkobject(L, 1);
2429 LuaEntitySAO *co = getluaobject(ref);
2430 if(co == NULL) return 0;
2432 v3f pos = checkFloatPos(L, 2);
2434 co->setVelocity(pos);
2438 // getvelocity(self)
2439 static int l_getvelocity(lua_State *L)
2441 ObjectRef *ref = checkobject(L, 1);
2442 LuaEntitySAO *co = getluaobject(ref);
2443 if(co == NULL) return 0;
2445 v3f v = co->getVelocity();
2450 // setacceleration(self, {x=num, y=num, z=num})
2451 static int l_setacceleration(lua_State *L)
2453 ObjectRef *ref = checkobject(L, 1);
2454 LuaEntitySAO *co = getluaobject(ref);
2455 if(co == NULL) return 0;
2457 v3f pos = checkFloatPos(L, 2);
2459 co->setAcceleration(pos);
2463 // getacceleration(self)
2464 static int l_getacceleration(lua_State *L)
2466 ObjectRef *ref = checkobject(L, 1);
2467 LuaEntitySAO *co = getluaobject(ref);
2468 if(co == NULL) return 0;
2470 v3f v = co->getAcceleration();
2475 // setyaw(self, radians)
2476 static int l_setyaw(lua_State *L)
2478 ObjectRef *ref = checkobject(L, 1);
2479 LuaEntitySAO *co = getluaobject(ref);
2480 if(co == NULL) return 0;
2482 float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
2489 static int l_getyaw(lua_State *L)
2491 ObjectRef *ref = checkobject(L, 1);
2492 LuaEntitySAO *co = getluaobject(ref);
2493 if(co == NULL) return 0;
2495 float yaw = co->getYaw() * core::DEGTORAD;
2496 lua_pushnumber(L, yaw);
2500 // settexturemod(self, mod)
2501 static int l_settexturemod(lua_State *L)
2503 ObjectRef *ref = checkobject(L, 1);
2504 LuaEntitySAO *co = getluaobject(ref);
2505 if(co == NULL) return 0;
2507 std::string mod = luaL_checkstring(L, 2);
2508 co->setTextureMod(mod);
2512 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
2513 // select_horiz_by_yawpitch=false)
2514 static int l_setsprite(lua_State *L)
2516 ObjectRef *ref = checkobject(L, 1);
2517 LuaEntitySAO *co = getluaobject(ref);
2518 if(co == NULL) return 0;
2521 if(!lua_isnil(L, 2))
2522 p = read_v2s16(L, 2);
2524 if(!lua_isnil(L, 3))
2525 num_frames = lua_tonumber(L, 3);
2526 float framelength = 0.2;
2527 if(!lua_isnil(L, 4))
2528 framelength = lua_tonumber(L, 4);
2529 bool select_horiz_by_yawpitch = false;
2530 if(!lua_isnil(L, 5))
2531 select_horiz_by_yawpitch = lua_toboolean(L, 5);
2532 co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
2537 // get_entity_name(self)
2538 static int l_get_entity_name(lua_State *L)
2540 ObjectRef *ref = checkobject(L, 1);
2541 LuaEntitySAO *co = getluaobject(ref);
2542 if(co == NULL) return 0;
2544 std::string name = co->getName();
2545 lua_pushstring(L, name.c_str());
2549 // get_luaentity(self)
2550 static int l_get_luaentity(lua_State *L)
2552 ObjectRef *ref = checkobject(L, 1);
2553 LuaEntitySAO *co = getluaobject(ref);
2554 if(co == NULL) return 0;
2556 luaentity_get(L, co->getId());
2562 // get_player_name(self)
2563 static int l_get_player_name(lua_State *L)
2565 ObjectRef *ref = checkobject(L, 1);
2566 ServerRemotePlayer *player = getplayer(ref);
2572 lua_pushstring(L, player->getName());
2576 // get_look_dir(self)
2577 static int l_get_look_dir(lua_State *L)
2579 ObjectRef *ref = checkobject(L, 1);
2580 ServerRemotePlayer *player = getplayer(ref);
2581 if(player == NULL) return 0;
2583 float pitch = player->getRadPitch();
2584 float yaw = player->getRadYaw();
2585 v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
2590 // get_look_pitch(self)
2591 static int l_get_look_pitch(lua_State *L)
2593 ObjectRef *ref = checkobject(L, 1);
2594 ServerRemotePlayer *player = getplayer(ref);
2595 if(player == NULL) return 0;
2597 lua_pushnumber(L, player->getRadPitch());
2601 // get_look_yaw(self)
2602 static int l_get_look_yaw(lua_State *L)
2604 ObjectRef *ref = checkobject(L, 1);
2605 ServerRemotePlayer *player = getplayer(ref);
2606 if(player == NULL) return 0;
2608 lua_pushnumber(L, player->getRadYaw());
2613 ObjectRef(ServerActiveObject *object):
2616 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
2622 infostream<<"ObjectRef destructing for id="
2623 <<m_object->getId()<<std::endl;
2625 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
2628 // Creates an ObjectRef and leaves it on top of stack
2629 // Not callable from Lua; all references are created on the C side.
2630 static void create(lua_State *L, ServerActiveObject *object)
2632 ObjectRef *o = new ObjectRef(object);
2633 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
2634 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
2635 luaL_getmetatable(L, className);
2636 lua_setmetatable(L, -2);
2639 static void set_null(lua_State *L)
2641 ObjectRef *o = checkobject(L, -1);
2645 static void Register(lua_State *L)
2648 int methodtable = lua_gettop(L);
2649 luaL_newmetatable(L, className);
2650 int metatable = lua_gettop(L);
2652 lua_pushliteral(L, "__metatable");
2653 lua_pushvalue(L, methodtable);
2654 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
2656 lua_pushliteral(L, "__index");
2657 lua_pushvalue(L, methodtable);
2658 lua_settable(L, metatable);
2660 lua_pushliteral(L, "__gc");
2661 lua_pushcfunction(L, gc_object);
2662 lua_settable(L, metatable);
2664 lua_pop(L, 1); // drop metatable
2666 luaL_openlib(L, 0, methods, 0); // fill methodtable
2667 lua_pop(L, 1); // drop methodtable
2669 // Cannot be created from Lua
2670 //lua_register(L, className, create_object);
2673 const char ObjectRef::className[] = "ObjectRef";
2674 const luaL_reg ObjectRef::methods[] = {
2675 // ServerActiveObject
2676 method(ObjectRef, remove),
2677 method(ObjectRef, getpos),
2678 method(ObjectRef, setpos),
2679 method(ObjectRef, moveto),
2680 method(ObjectRef, punch),
2681 method(ObjectRef, right_click),
2682 method(ObjectRef, set_hp),
2683 method(ObjectRef, get_hp),
2684 method(ObjectRef, get_inventory),
2685 method(ObjectRef, get_wield_list),
2686 method(ObjectRef, get_wield_index),
2687 method(ObjectRef, get_wielded_item),
2688 method(ObjectRef, set_wielded_item),
2689 // LuaEntitySAO-only
2690 method(ObjectRef, setvelocity),
2691 method(ObjectRef, getvelocity),
2692 method(ObjectRef, setacceleration),
2693 method(ObjectRef, getacceleration),
2694 method(ObjectRef, setyaw),
2695 method(ObjectRef, getyaw),
2696 method(ObjectRef, settexturemod),
2697 method(ObjectRef, setsprite),
2698 method(ObjectRef, get_entity_name),
2699 method(ObjectRef, get_luaentity),
2701 method(ObjectRef, get_player_name),
2702 method(ObjectRef, get_look_dir),
2703 method(ObjectRef, get_look_pitch),
2704 method(ObjectRef, get_look_yaw),
2708 // Creates a new anonymous reference if id=0
2709 static void objectref_get_or_create(lua_State *L,
2710 ServerActiveObject *cobj)
2712 if(cobj->getId() == 0){
2713 ObjectRef::create(L, cobj);
2715 objectref_get(L, cobj->getId());
2726 ServerEnvironment *m_env;
2728 static const char className[];
2729 static const luaL_reg methods[];
2731 static EnvRef *checkobject(lua_State *L, int narg)
2733 luaL_checktype(L, narg, LUA_TUSERDATA);
2734 void *ud = luaL_checkudata(L, narg, className);
2735 if(!ud) luaL_typerror(L, narg, className);
2736 return *(EnvRef**)ud; // unbox pointer
2739 // Exported functions
2741 // EnvRef:add_node(pos, node)
2742 // pos = {x=num, y=num, z=num}
2743 static int l_add_node(lua_State *L)
2745 //infostream<<"EnvRef::l_add_node()"<<std::endl;
2746 EnvRef *o = checkobject(L, 1);
2747 ServerEnvironment *env = o->m_env;
2748 if(env == NULL) return 0;
2750 v3s16 pos = read_v3s16(L, 2);
2752 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
2754 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
2755 lua_pushboolean(L, succeeded);
2759 // EnvRef:remove_node(pos)
2760 // pos = {x=num, y=num, z=num}
2761 static int l_remove_node(lua_State *L)
2763 //infostream<<"EnvRef::l_remove_node()"<<std::endl;
2764 EnvRef *o = checkobject(L, 1);
2765 ServerEnvironment *env = o->m_env;
2766 if(env == NULL) return 0;
2768 v3s16 pos = read_v3s16(L, 2);
2770 bool succeeded = env->getMap().removeNodeWithEvent(pos);
2771 lua_pushboolean(L, succeeded);
2775 // EnvRef:get_node(pos)
2776 // pos = {x=num, y=num, z=num}
2777 static int l_get_node(lua_State *L)
2779 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2780 EnvRef *o = checkobject(L, 1);
2781 ServerEnvironment *env = o->m_env;
2782 if(env == NULL) return 0;
2784 v3s16 pos = read_v3s16(L, 2);
2786 MapNode n = env->getMap().getNodeNoEx(pos);
2788 pushnode(L, n, env->getGameDef()->ndef());
2792 // EnvRef:get_node_or_nil(pos)
2793 // pos = {x=num, y=num, z=num}
2794 static int l_get_node_or_nil(lua_State *L)
2796 //infostream<<"EnvRef::l_get_node()"<<std::endl;
2797 EnvRef *o = checkobject(L, 1);
2798 ServerEnvironment *env = o->m_env;
2799 if(env == NULL) return 0;
2801 v3s16 pos = read_v3s16(L, 2);
2804 MapNode n = env->getMap().getNode(pos);
2806 pushnode(L, n, env->getGameDef()->ndef());
2808 } catch(InvalidPositionException &e)
2815 // EnvRef:get_node_light(pos, timeofday)
2816 // pos = {x=num, y=num, z=num}
2817 // timeofday: nil = current time, 0 = night, 0.5 = day
2818 static int l_get_node_light(lua_State *L)
2820 EnvRef *o = checkobject(L, 1);
2821 ServerEnvironment *env = o->m_env;
2822 if(env == NULL) return 0;
2824 v3s16 pos = read_v3s16(L, 2);
2825 u32 time_of_day = env->getTimeOfDay();
2826 if(lua_isnumber(L, 3))
2827 time_of_day = 24000.0 * lua_tonumber(L, 3);
2828 time_of_day %= 24000;
2829 u32 dnr = time_to_daynight_ratio(time_of_day);
2830 MapNode n = env->getMap().getNodeNoEx(pos);
2832 MapNode n = env->getMap().getNode(pos);
2833 INodeDefManager *ndef = env->getGameDef()->ndef();
2834 lua_pushinteger(L, n.getLightBlend(dnr, ndef));
2836 } catch(InvalidPositionException &e)
2843 // EnvRef:add_entity(pos, entityname) -> ObjectRef or nil
2844 // pos = {x=num, y=num, z=num}
2845 static int l_add_entity(lua_State *L)
2847 //infostream<<"EnvRef::l_add_entity()"<<std::endl;
2848 EnvRef *o = checkobject(L, 1);
2849 ServerEnvironment *env = o->m_env;
2850 if(env == NULL) return 0;
2852 v3f pos = checkFloatPos(L, 2);
2854 const char *name = luaL_checkstring(L, 3);
2856 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
2857 int objectid = env->addActiveObject(obj);
2858 // If failed to add, return nothing (reads as nil)
2862 objectref_get_or_create(L, obj);
2866 // EnvRef:add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil
2867 // pos = {x=num, y=num, z=num}
2868 static int l_add_item(lua_State *L)
2870 //infostream<<"EnvRef::l_add_item()"<<std::endl;
2871 EnvRef *o = checkobject(L, 1);
2872 ServerEnvironment *env = o->m_env;
2873 if(env == NULL) return 0;
2875 v3f pos = checkFloatPos(L, 2);
2877 ItemStack item = read_item(L, 3);
2878 if(item.empty() || !item.isKnown(get_server(L)->idef()))
2881 ServerActiveObject *obj = new ItemSAO(env, pos, item.getItemString());
2882 int objectid = env->addActiveObject(obj);
2883 // If failed to add, return nothing (reads as nil)
2887 objectref_get_or_create(L, obj);
2891 // EnvRef:add_rat(pos)
2892 // pos = {x=num, y=num, z=num}
2893 static int l_add_rat(lua_State *L)
2895 infostream<<"EnvRef::l_add_rat()"<<std::endl;
2896 EnvRef *o = checkobject(L, 1);
2897 ServerEnvironment *env = o->m_env;
2898 if(env == NULL) return 0;
2900 v3f pos = checkFloatPos(L, 2);
2902 ServerActiveObject *obj = new RatSAO(env, pos);
2903 env->addActiveObject(obj);
2907 // EnvRef:add_firefly(pos)
2908 // pos = {x=num, y=num, z=num}
2909 static int l_add_firefly(lua_State *L)
2911 infostream<<"EnvRef::l_add_firefly()"<<std::endl;
2912 EnvRef *o = checkobject(L, 1);
2913 ServerEnvironment *env = o->m_env;
2914 if(env == NULL) return 0;
2916 v3f pos = checkFloatPos(L, 2);
2918 ServerActiveObject *obj = new FireflySAO(env, pos);
2919 env->addActiveObject(obj);
2923 // EnvRef:get_meta(pos)
2924 static int l_get_meta(lua_State *L)
2926 //infostream<<"EnvRef::l_get_meta()"<<std::endl;
2927 EnvRef *o = checkobject(L, 1);
2928 ServerEnvironment *env = o->m_env;
2929 if(env == NULL) return 0;
2931 v3s16 p = read_v3s16(L, 2);
2932 NodeMetaRef::create(L, p, env);
2936 // EnvRef:get_player_by_name(name)
2937 static int l_get_player_by_name(lua_State *L)
2939 EnvRef *o = checkobject(L, 1);
2940 ServerEnvironment *env = o->m_env;
2941 if(env == NULL) return 0;
2943 const char *name = luaL_checkstring(L, 2);
2944 ServerRemotePlayer *player =
2945 static_cast<ServerRemotePlayer*>(env->getPlayer(name));
2950 // Put player on stack
2951 objectref_get_or_create(L, player);
2955 // EnvRef:get_objects_inside_radius(pos, radius)
2956 static int l_get_objects_inside_radius(lua_State *L)
2958 // Get the table insert function
2959 lua_getglobal(L, "table");
2960 lua_getfield(L, -1, "insert");
2961 int table_insert = lua_gettop(L);
2963 EnvRef *o = checkobject(L, 1);
2964 ServerEnvironment *env = o->m_env;
2965 if(env == NULL) return 0;
2967 v3f pos = checkFloatPos(L, 2);
2968 float radius = luaL_checknumber(L, 3) * BS;
2969 std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
2971 int table = lua_gettop(L);
2972 for(std::set<u16>::const_iterator
2973 i = ids.begin(); i != ids.end(); i++){
2974 ServerActiveObject *obj = env->getActiveObject(*i);
2975 // Insert object reference into table
2976 lua_pushvalue(L, table_insert);
2977 lua_pushvalue(L, table);
2978 objectref_get_or_create(L, obj);
2979 if(lua_pcall(L, 2, 0, 0))
2980 script_error(L, "error: %s", lua_tostring(L, -1));
2985 // EnvRef:set_timeofday(val)
2987 static int l_set_timeofday(lua_State *L)
2989 EnvRef *o = checkobject(L, 1);
2990 ServerEnvironment *env = o->m_env;
2991 if(env == NULL) return 0;
2993 float timeofday_f = luaL_checknumber(L, 2);
2994 assert(timeofday_f >= 0.0 && timeofday_f <= 1.0);
2995 int timeofday_mh = (int)(timeofday_f * 24000.0);
2996 // This should be set directly in the environment but currently
2997 // such changes aren't immediately sent to the clients, so call
2998 // the server instead.
2999 //env->setTimeOfDay(timeofday_mh);
3000 get_server(L)->setTimeOfDay(timeofday_mh);
3004 // EnvRef:get_timeofday() -> 0...1
3005 static int l_get_timeofday(lua_State *L)
3007 EnvRef *o = checkobject(L, 1);
3008 ServerEnvironment *env = o->m_env;
3009 if(env == NULL) return 0;
3011 int timeofday_mh = env->getTimeOfDay();
3012 float timeofday_f = (float)timeofday_mh / 24000.0;
3013 lua_pushnumber(L, timeofday_f);
3017 static int gc_object(lua_State *L) {
3018 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
3024 EnvRef(ServerEnvironment *env):
3027 infostream<<"EnvRef created"<<std::endl;
3032 infostream<<"EnvRef destructing"<<std::endl;
3035 // Creates an EnvRef and leaves it on top of stack
3036 // Not callable from Lua; all references are created on the C side.
3037 static void create(lua_State *L, ServerEnvironment *env)
3039 EnvRef *o = new EnvRef(env);
3040 //infostream<<"EnvRef::create: o="<<o<<std::endl;
3041 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
3042 luaL_getmetatable(L, className);
3043 lua_setmetatable(L, -2);
3046 static void set_null(lua_State *L)
3048 EnvRef *o = checkobject(L, -1);
3052 static void Register(lua_State *L)
3055 int methodtable = lua_gettop(L);
3056 luaL_newmetatable(L, className);
3057 int metatable = lua_gettop(L);
3059 lua_pushliteral(L, "__metatable");
3060 lua_pushvalue(L, methodtable);
3061 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
3063 lua_pushliteral(L, "__index");
3064 lua_pushvalue(L, methodtable);
3065 lua_settable(L, metatable);
3067 lua_pushliteral(L, "__gc");
3068 lua_pushcfunction(L, gc_object);
3069 lua_settable(L, metatable);
3071 lua_pop(L, 1); // drop metatable
3073 luaL_openlib(L, 0, methods, 0); // fill methodtable
3074 lua_pop(L, 1); // drop methodtable
3076 // Cannot be created from Lua
3077 //lua_register(L, className, create_object);
3080 const char EnvRef::className[] = "EnvRef";
3081 const luaL_reg EnvRef::methods[] = {
3082 method(EnvRef, add_node),
3083 method(EnvRef, remove_node),
3084 method(EnvRef, get_node),
3085 method(EnvRef, get_node_or_nil),
3086 method(EnvRef, get_node_light),
3087 method(EnvRef, add_entity),
3088 method(EnvRef, add_item),
3089 method(EnvRef, add_rat),
3090 method(EnvRef, add_firefly),
3091 method(EnvRef, get_meta),
3092 method(EnvRef, get_player_by_name),
3093 method(EnvRef, get_objects_inside_radius),
3094 method(EnvRef, set_timeofday),
3095 method(EnvRef, get_timeofday),
3103 class LuaABM : public ActiveBlockModifier
3109 std::set<std::string> m_trigger_contents;
3110 std::set<std::string> m_required_neighbors;
3111 float m_trigger_interval;
3112 u32 m_trigger_chance;
3114 LuaABM(lua_State *L, int id,
3115 const std::set<std::string> &trigger_contents,
3116 const std::set<std::string> &required_neighbors,
3117 float trigger_interval, u32 trigger_chance):
3120 m_trigger_contents(trigger_contents),
3121 m_required_neighbors(required_neighbors),
3122 m_trigger_interval(trigger_interval),
3123 m_trigger_chance(trigger_chance)
3126 virtual std::set<std::string> getTriggerContents()
3128 return m_trigger_contents;
3130 virtual std::set<std::string> getRequiredNeighbors()
3132 return m_required_neighbors;
3134 virtual float getTriggerInterval()
3136 return m_trigger_interval;
3138 virtual u32 getTriggerChance()
3140 return m_trigger_chance;
3142 virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
3143 u32 active_object_count, u32 active_object_count_wider)
3145 lua_State *L = m_lua;
3148 assert(lua_checkstack(L, 20));
3149 StackUnroller stack_unroller(L);
3151 // Get minetest.registered_abms
3152 lua_getglobal(L, "minetest");
3153 lua_getfield(L, -1, "registered_abms");
3154 luaL_checktype(L, -1, LUA_TTABLE);
3155 int registered_abms = lua_gettop(L);
3157 // Get minetest.registered_abms[m_id]
3158 lua_pushnumber(L, m_id);
3159 lua_gettable(L, registered_abms);
3160 if(lua_isnil(L, -1))
3164 luaL_checktype(L, -1, LUA_TTABLE);
3165 lua_getfield(L, -1, "action");
3166 luaL_checktype(L, -1, LUA_TFUNCTION);
3168 pushnode(L, n, env->getGameDef()->ndef());
3169 lua_pushnumber(L, active_object_count);
3170 lua_pushnumber(L, active_object_count_wider);
3171 if(lua_pcall(L, 4, 0, 0))
3172 script_error(L, "error: %s", lua_tostring(L, -1));
3177 // Writes a line to dstream
3178 static int l_debug(lua_State *L)
3180 std::string text = lua_tostring(L, 1);
3181 dstream << text << std::endl;
3185 // log([level,] text)
3186 // Writes a line to the logger.
3187 // The one-argument version logs to infostream.
3188 // The two-argument version accept a log level: error, action, info, or verbose.
3189 static int l_log(lua_State *L)
3192 LogMessageLevel level = LMT_INFO;
3193 if(lua_isnone(L, 2))
3195 text = lua_tostring(L, 1);
3199 std::string levelname = lua_tostring(L, 1);
3200 text = lua_tostring(L, 2);
3201 if(levelname == "error")
3203 else if(levelname == "action")
3205 else if(levelname == "verbose")
3206 level = LMT_VERBOSE;
3208 log_printline(level, text);
3212 // register_item_raw({lots of stuff})
3213 static int l_register_item_raw(lua_State *L)
3215 luaL_checktype(L, 1, LUA_TTABLE);
3218 // Get the writable item and node definition managers from the server
3219 IWritableItemDefManager *idef =
3220 get_server(L)->getWritableItemDefManager();
3221 IWritableNodeDefManager *ndef =
3222 get_server(L)->getWritableNodeDefManager();
3224 // Check if name is defined
3225 lua_getfield(L, table, "name");
3226 if(lua_isstring(L, -1)){
3227 std::string name = lua_tostring(L, -1);
3228 infostream<<"register_item_raw: "<<name<<std::endl;
3230 throw LuaError(L, "register_item_raw: name is not defined or not a string");
3233 // Check if on_use is defined
3235 // Read the item definition and register it
3236 ItemDefinition def = read_item_definition(L, table);
3237 idef->registerItem(def);
3239 // Read the node definition (content features) and register it
3240 if(def.type == ITEM_NODE)
3242 ContentFeatures f = read_content_features(L, table);
3243 ndef->set(f.name, f);
3246 return 0; /* number of results */
3249 // register_alias_raw(name, convert_to_name)
3250 static int l_register_alias_raw(lua_State *L)
3252 std::string name = luaL_checkstring(L, 1);
3253 std::string convert_to = luaL_checkstring(L, 2);
3255 // Get the writable item definition manager from the server
3256 IWritableItemDefManager *idef =
3257 get_server(L)->getWritableItemDefManager();
3259 idef->registerAlias(name, convert_to);
3261 return 0; /* number of results */
3264 // helper for register_craft
3265 static bool read_craft_recipe_shaped(lua_State *L, int index,
3266 int &width, std::vector<std::string> &recipe)
3269 index = lua_gettop(L) + 1 + index;
3271 if(!lua_istable(L, index))
3276 while(lua_next(L, index) != 0){
3278 // key at index -2 and value at index -1
3279 if(!lua_istable(L, -1))
3281 int table2 = lua_gettop(L);
3283 while(lua_next(L, table2) != 0){
3284 // key at index -2 and value at index -1
3285 if(!lua_isstring(L, -1))
3287 recipe.push_back(lua_tostring(L, -1));
3288 // removes value, keeps key for next iteration
3295 if(colcount != width)
3298 // removes value, keeps key for next iteration
3305 // helper for register_craft
3306 static bool read_craft_recipe_shapeless(lua_State *L, int index,
3307 std::vector<std::string> &recipe)
3310 index = lua_gettop(L) + 1 + index;
3312 if(!lua_istable(L, index))
3316 while(lua_next(L, index) != 0){
3317 // key at index -2 and value at index -1
3318 if(!lua_isstring(L, -1))
3320 recipe.push_back(lua_tostring(L, -1));
3321 // removes value, keeps key for next iteration
3327 // helper for register_craft
3328 static bool read_craft_replacements(lua_State *L, int index,
3329 CraftReplacements &replacements)
3332 index = lua_gettop(L) + 1 + index;
3334 if(!lua_istable(L, index))
3338 while(lua_next(L, index) != 0){
3339 // key at index -2 and value at index -1
3340 if(!lua_istable(L, -1))
3342 lua_rawgeti(L, -1, 1);
3343 if(!lua_isstring(L, -1))
3345 std::string replace_from = lua_tostring(L, -1);
3347 lua_rawgeti(L, -1, 2);
3348 if(!lua_isstring(L, -1))
3350 std::string replace_to = lua_tostring(L, -1);
3352 replacements.pairs.push_back(
3353 std::make_pair(replace_from, replace_to));
3354 // removes value, keeps key for next iteration
3359 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
3360 static int l_register_craft(lua_State *L)
3362 //infostream<<"register_craft"<<std::endl;
3363 luaL_checktype(L, 1, LUA_TTABLE);
3366 // Get the writable craft definition manager from the server
3367 IWritableCraftDefManager *craftdef =
3368 get_server(L)->getWritableCraftDefManager();
3370 std::string type = getstringfield_default(L, table, "type", "shaped");
3373 CraftDefinitionShaped
3375 if(type == "shaped"){
3376 std::string output = getstringfield_default(L, table, "output", "");
3378 throw LuaError(L, "Crafting definition is missing an output");
3381 std::vector<std::string> recipe;
3382 lua_getfield(L, table, "recipe");
3383 if(lua_isnil(L, -1))
3384 throw LuaError(L, "Crafting definition is missing a recipe"
3385 " (output=\"" + output + "\")");
3386 if(!read_craft_recipe_shaped(L, -1, width, recipe))
3387 throw LuaError(L, "Invalid crafting recipe"
3388 " (output=\"" + output + "\")");
3390 CraftReplacements replacements;
3391 lua_getfield(L, table, "replacements");
3392 if(!lua_isnil(L, -1))
3394 if(!read_craft_replacements(L, -1, replacements))
3395 throw LuaError(L, "Invalid replacements"
3396 " (output=\"" + output + "\")");
3399 CraftDefinition *def = new CraftDefinitionShaped(
3400 output, width, recipe, replacements);
3401 craftdef->registerCraft(def);
3404 CraftDefinitionShapeless
3406 else if(type == "shapeless"){
3407 std::string output = getstringfield_default(L, table, "output", "");
3409 throw LuaError(L, "Crafting definition (shapeless)"
3410 " is missing an output");
3412 std::vector<std::string> recipe;
3413 lua_getfield(L, table, "recipe");
3414 if(lua_isnil(L, -1))
3415 throw LuaError(L, "Crafting definition (shapeless)"
3416 " is missing a recipe"
3417 " (output=\"" + output + "\")");
3418 if(!read_craft_recipe_shapeless(L, -1, recipe))
3419 throw LuaError(L, "Invalid crafting recipe"
3420 " (output=\"" + output + "\")");
3422 CraftReplacements replacements;
3423 lua_getfield(L, table, "replacements");
3424 if(!lua_isnil(L, -1))
3426 if(!read_craft_replacements(L, -1, replacements))
3427 throw LuaError(L, "Invalid replacements"
3428 " (output=\"" + output + "\")");
3431 CraftDefinition *def = new CraftDefinitionShapeless(
3432 output, recipe, replacements);
3433 craftdef->registerCraft(def);
3436 CraftDefinitionToolRepair
3438 else if(type == "toolrepair"){
3439 float additional_wear = getfloatfield_default(L, table,
3440 "additional_wear", 0.0);
3442 CraftDefinition *def = new CraftDefinitionToolRepair(
3444 craftdef->registerCraft(def);
3447 CraftDefinitionCooking
3449 else if(type == "cooking"){
3450 std::string output = getstringfield_default(L, table, "output", "");
3452 throw LuaError(L, "Crafting definition (cooking)"
3453 " is missing an output");
3455 std::string recipe = getstringfield_default(L, table, "recipe", "");
3457 throw LuaError(L, "Crafting definition (cooking)"
3458 " is missing a recipe"
3459 " (output=\"" + output + "\")");
3461 float cooktime = getfloatfield_default(L, table, "cooktime", 3.0);
3463 CraftDefinition *def = new CraftDefinitionCooking(
3464 output, recipe, cooktime);
3465 craftdef->registerCraft(def);
3470 else if(type == "fuel"){
3471 std::string recipe = getstringfield_default(L, table, "recipe", "");
3473 throw LuaError(L, "Crafting definition (fuel)"
3474 " is missing a recipe");
3476 float burntime = getfloatfield_default(L, table, "burntime", 1.0);
3478 CraftDefinition *def = new CraftDefinitionFuel(
3480 craftdef->registerCraft(def);
3484 throw LuaError(L, "Unknown crafting definition type: \"" + type + "\"");
3488 return 0; /* number of results */
3491 // setting_get(name)
3492 static int l_setting_get(lua_State *L)
3494 const char *name = luaL_checkstring(L, 1);
3496 std::string value = g_settings->get(name);
3497 lua_pushstring(L, value.c_str());
3498 } catch(SettingNotFoundException &e){
3504 // setting_getbool(name)
3505 static int l_setting_getbool(lua_State *L)
3507 const char *name = luaL_checkstring(L, 1);
3509 bool value = g_settings->getBool(name);
3510 lua_pushboolean(L, value);
3511 } catch(SettingNotFoundException &e){
3517 // chat_send_all(text)
3518 static int l_chat_send_all(lua_State *L)
3520 const char *text = luaL_checkstring(L, 1);
3521 // Get server from registry
3522 Server *server = get_server(L);
3524 server->notifyPlayers(narrow_to_wide(text));
3528 // chat_send_player(name, text)
3529 static int l_chat_send_player(lua_State *L)
3531 const char *name = luaL_checkstring(L, 1);
3532 const char *text = luaL_checkstring(L, 2);
3533 // Get server from registry
3534 Server *server = get_server(L);
3536 server->notifyPlayer(name, narrow_to_wide(text));
3540 // get_player_privs(name, text)
3541 static int l_get_player_privs(lua_State *L)
3543 const char *name = luaL_checkstring(L, 1);
3544 // Get server from registry
3545 Server *server = get_server(L);
3548 int table = lua_gettop(L);
3549 u64 privs_i = server->getPlayerAuthPrivs(name);
3550 // Special case for the "name" setting (local player / server owner)
3551 if(name == g_settings->get("name"))
3553 std::set<std::string> privs_s = privsToSet(privs_i);
3554 for(std::set<std::string>::const_iterator
3555 i = privs_s.begin(); i != privs_s.end(); i++){
3556 lua_pushboolean(L, true);
3557 lua_setfield(L, table, i->c_str());
3559 lua_pushvalue(L, table);
3563 // get_inventory(location)
3564 static int l_get_inventory(lua_State *L)
3566 InventoryLocation loc;
3568 std::string type = checkstringfield(L, 1, "type");
3569 if(type == "player"){
3570 std::string name = checkstringfield(L, 1, "name");
3571 loc.setPlayer(name);
3572 } else if(type == "node"){
3573 lua_getfield(L, 1, "pos");
3574 v3s16 pos = check_v3s16(L, -1);
3575 loc.setNodeMeta(pos);
3578 if(get_server(L)->getInventory(loc) != NULL)
3579 InvRef::create(L, loc);
3585 // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
3586 static int l_get_dig_params(lua_State *L)
3588 std::map<std::string, int> groups;
3589 read_groups(L, 1, groups);
3590 ToolCapabilities tp = read_tool_capabilities(L, 2);
3591 if(lua_isnoneornil(L, 3))
3592 push_dig_params(L, getDigParams(groups, &tp));
3594 push_dig_params(L, getDigParams(groups, &tp,
3595 luaL_checknumber(L, 3)));
3599 // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
3600 static int l_get_hit_params(lua_State *L)
3602 std::map<std::string, int> groups;
3603 read_groups(L, 1, groups);
3604 ToolCapabilities tp = read_tool_capabilities(L, 2);
3605 if(lua_isnoneornil(L, 3))
3606 push_hit_params(L, getHitParams(groups, &tp));
3608 push_hit_params(L, getHitParams(groups, &tp,
3609 luaL_checknumber(L, 3)));
3613 // get_current_modname()
3614 static int l_get_current_modname(lua_State *L)
3616 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
3620 // get_modpath(modname)
3621 static int l_get_modpath(lua_State *L)
3623 const char *modname = luaL_checkstring(L, 1);
3625 const ModSpec *mod = get_server(L)->getModSpec(modname);
3630 lua_pushstring(L, mod->path.c_str());
3635 static int l_get_worldpath(lua_State *L)
3637 std::string worldpath = get_server(L)->getWorldPath();
3638 lua_pushstring(L, worldpath.c_str());
3642 static const struct luaL_Reg minetest_f [] = {
3645 {"register_item_raw", l_register_item_raw},
3646 {"register_alias_raw", l_register_alias_raw},
3647 {"register_craft", l_register_craft},
3648 {"setting_get", l_setting_get},
3649 {"setting_getbool", l_setting_getbool},
3650 {"chat_send_all", l_chat_send_all},
3651 {"chat_send_player", l_chat_send_player},
3652 {"get_player_privs", l_get_player_privs},
3653 {"get_inventory", l_get_inventory},
3654 {"get_dig_params", l_get_dig_params},
3655 {"get_hit_params", l_get_hit_params},
3656 {"get_current_modname", l_get_current_modname},
3657 {"get_modpath", l_get_modpath},
3658 {"get_worldpath", l_get_worldpath},
3663 Main export function
3666 void scriptapi_export(lua_State *L, Server *server)
3669 assert(lua_checkstack(L, 20));
3670 infostream<<"scriptapi_export"<<std::endl;
3671 StackUnroller stack_unroller(L);
3673 // Store server as light userdata in registry
3674 lua_pushlightuserdata(L, server);
3675 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
3677 // Register global functions in table minetest
3679 luaL_register(L, NULL, minetest_f);
3680 lua_setglobal(L, "minetest");
3682 // Get the main minetest table
3683 lua_getglobal(L, "minetest");
3685 // Add tables to minetest
3688 lua_setfield(L, -2, "object_refs");
3690 lua_setfield(L, -2, "luaentities");
3692 // Register wrappers
3693 LuaItemStack::Register(L);
3694 InvRef::Register(L);
3695 NodeMetaRef::Register(L);
3696 ObjectRef::Register(L);
3697 EnvRef::Register(L);
3700 bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
3701 const std::string &modname)
3703 ModNameStorer modnamestorer(L, modname);
3705 if(!string_allowed(modname, "abcdefghijklmnopqrstuvwxyz"
3707 errorstream<<"Error loading mod \""<<modname
3708 <<"\": modname does not follow naming conventions: "
3709 <<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
3713 bool success = false;
3716 success = script_load(L, scriptpath.c_str());
3719 errorstream<<"Error loading mod \""<<modname
3720 <<"\": "<<e.what()<<std::endl;
3726 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
3729 assert(lua_checkstack(L, 20));
3730 infostream<<"scriptapi_add_environment"<<std::endl;
3731 StackUnroller stack_unroller(L);
3733 // Create EnvRef on stack
3734 EnvRef::create(L, env);
3735 int envref = lua_gettop(L);
3737 // minetest.env = envref
3738 lua_getglobal(L, "minetest");
3739 luaL_checktype(L, -1, LUA_TTABLE);
3740 lua_pushvalue(L, envref);
3741 lua_setfield(L, -2, "env");
3743 // Store environment as light userdata in registry
3744 lua_pushlightuserdata(L, env);
3745 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
3748 Add ActiveBlockModifiers to environment
3751 // Get minetest.registered_abms
3752 lua_getglobal(L, "minetest");
3753 lua_getfield(L, -1, "registered_abms");
3754 luaL_checktype(L, -1, LUA_TTABLE);
3755 int registered_abms = lua_gettop(L);
3757 if(lua_istable(L, registered_abms)){
3758 int table = lua_gettop(L);
3760 while(lua_next(L, table) != 0){
3761 // key at index -2 and value at index -1
3762 int id = lua_tonumber(L, -2);
3763 int current_abm = lua_gettop(L);
3765 std::set<std::string> trigger_contents;
3766 lua_getfield(L, current_abm, "nodenames");
3767 if(lua_istable(L, -1)){
3768 int table = lua_gettop(L);
3770 while(lua_next(L, table) != 0){
3771 // key at index -2 and value at index -1
3772 luaL_checktype(L, -1, LUA_TSTRING);
3773 trigger_contents.insert(lua_tostring(L, -1));
3774 // removes value, keeps key for next iteration
3777 } else if(lua_isstring(L, -1)){
3778 trigger_contents.insert(lua_tostring(L, -1));
3782 std::set<std::string> required_neighbors;
3783 lua_getfield(L, current_abm, "neighbors");
3784 if(lua_istable(L, -1)){
3785 int table = lua_gettop(L);
3787 while(lua_next(L, table) != 0){
3788 // key at index -2 and value at index -1
3789 luaL_checktype(L, -1, LUA_TSTRING);
3790 required_neighbors.insert(lua_tostring(L, -1));
3791 // removes value, keeps key for next iteration
3794 } else if(lua_isstring(L, -1)){
3795 required_neighbors.insert(lua_tostring(L, -1));
3799 float trigger_interval = 10.0;
3800 getfloatfield(L, current_abm, "interval", trigger_interval);
3802 int trigger_chance = 50;
3803 getintfield(L, current_abm, "chance", trigger_chance);
3805 LuaABM *abm = new LuaABM(L, id, trigger_contents,
3806 required_neighbors, trigger_interval, trigger_chance);
3808 env->addActiveBlockModifier(abm);
3810 // removes value, keeps key for next iteration
3818 // Dump stack top with the dump2 function
3819 static void dump2(lua_State *L, const char *name)
3821 // Dump object (debug)
3822 lua_getglobal(L, "dump2");
3823 luaL_checktype(L, -1, LUA_TFUNCTION);
3824 lua_pushvalue(L, -2); // Get previous stack top as first parameter
3825 lua_pushstring(L, name);
3826 if(lua_pcall(L, 2, 0, 0))
3827 script_error(L, "error: %s", lua_tostring(L, -1));
3835 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
3838 assert(lua_checkstack(L, 20));
3839 //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
3840 StackUnroller stack_unroller(L);
3842 // Create object on stack
3843 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
3844 int object = lua_gettop(L);
3846 // Get minetest.object_refs table
3847 lua_getglobal(L, "minetest");
3848 lua_getfield(L, -1, "object_refs");
3849 luaL_checktype(L, -1, LUA_TTABLE);
3850 int objectstable = lua_gettop(L);
3852 // object_refs[id] = object
3853 lua_pushnumber(L, cobj->getId()); // Push id
3854 lua_pushvalue(L, object); // Copy object to top of stack
3855 lua_settable(L, objectstable);
3858 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
3861 assert(lua_checkstack(L, 20));
3862 //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
3863 StackUnroller stack_unroller(L);
3865 // Get minetest.object_refs table
3866 lua_getglobal(L, "minetest");
3867 lua_getfield(L, -1, "object_refs");
3868 luaL_checktype(L, -1, LUA_TTABLE);
3869 int objectstable = lua_gettop(L);
3871 // Get object_refs[id]
3872 lua_pushnumber(L, cobj->getId()); // Push id
3873 lua_gettable(L, objectstable);
3874 // Set object reference to NULL
3875 ObjectRef::set_null(L);
3876 lua_pop(L, 1); // pop object
3878 // Set object_refs[id] = nil
3879 lua_pushnumber(L, cobj->getId()); // Push id
3881 lua_settable(L, objectstable);
3884 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
3885 const std::string &message)
3888 assert(lua_checkstack(L, 20));
3889 StackUnroller stack_unroller(L);
3891 // Get minetest.registered_on_chat_messages
3892 lua_getglobal(L, "minetest");
3893 lua_getfield(L, -1, "registered_on_chat_messages");
3894 luaL_checktype(L, -1, LUA_TTABLE);
3895 int table = lua_gettop(L);
3898 while(lua_next(L, table) != 0){
3899 // key at index -2 and value at index -1
3900 luaL_checktype(L, -1, LUA_TFUNCTION);
3902 lua_pushstring(L, name.c_str());
3903 lua_pushstring(L, message.c_str());
3904 if(lua_pcall(L, 2, 1, 0))
3905 script_error(L, "error: %s", lua_tostring(L, -1));
3906 bool ate = lua_toboolean(L, -1);
3910 // value removed, keep key for next iteration
3919 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
3922 assert(lua_checkstack(L, 20));
3923 StackUnroller stack_unroller(L);
3925 // Get minetest.registered_on_newplayers
3926 lua_getglobal(L, "minetest");
3927 lua_getfield(L, -1, "registered_on_newplayers");
3928 luaL_checktype(L, -1, LUA_TTABLE);
3929 int table = lua_gettop(L);
3932 while(lua_next(L, table) != 0){
3933 // key at index -2 and value at index -1
3934 luaL_checktype(L, -1, LUA_TFUNCTION);
3936 objectref_get_or_create(L, player);
3937 if(lua_pcall(L, 1, 0, 0))
3938 script_error(L, "error: %s", lua_tostring(L, -1));
3939 // value removed, keep key for next iteration
3943 void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player)
3946 assert(lua_checkstack(L, 20));
3947 StackUnroller stack_unroller(L);
3949 // Get minetest.registered_on_dieplayers
3950 lua_getglobal(L, "minetest");
3951 lua_getfield(L, -1, "registered_on_dieplayers");
3952 luaL_checktype(L, -1, LUA_TTABLE);
3953 int table = lua_gettop(L);
3956 while(lua_next(L, table) != 0){
3957 // key at index -2 and value at index -1
3958 luaL_checktype(L, -1, LUA_TFUNCTION);
3960 objectref_get_or_create(L, player);
3961 if(lua_pcall(L, 1, 0, 0))
3962 script_error(L, "error: %s", lua_tostring(L, -1));
3963 // value removed, keep key for next iteration
3968 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
3971 assert(lua_checkstack(L, 20));
3972 StackUnroller stack_unroller(L);
3974 dstream<<"player: "<<player<<" id: "<<player->getId()<<std::endl;
3976 bool positioning_handled_by_some = false;
3978 // Get minetest.registered_on_respawnplayers
3979 lua_getglobal(L, "minetest");
3980 lua_getfield(L, -1, "registered_on_respawnplayers");
3981 luaL_checktype(L, -1, LUA_TTABLE);
3982 int table = lua_gettop(L);
3985 while(lua_next(L, table) != 0){
3986 // key at index -2 and value at index -1
3987 luaL_checktype(L, -1, LUA_TFUNCTION);
3989 objectref_get_or_create(L, player);
3990 if(lua_pcall(L, 1, 1, 0))
3991 script_error(L, "error: %s", lua_tostring(L, -1));
3992 bool positioning_handled = lua_toboolean(L, -1);
3994 if(positioning_handled)
3995 positioning_handled_by_some = true;
3996 // value removed, keep key for next iteration
3998 return positioning_handled_by_some;
4001 void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
4003 lua_getglobal(L, "minetest");
4004 lua_getfield(L, -1, "creative_inventory");
4005 luaL_checktype(L, -1, LUA_TTABLE);
4006 inventory_set_list_from_lua(&player->inventory, "main", L, -1,
4007 PLAYER_INVENTORY_SIZE);
4011 item callbacks and node callbacks
4014 // Retrieves minetest.registered_items[name][callbackname]
4015 // If that is nil or on error, return false and stack is unchanged
4016 // If that is a function, returns true and pushes the
4017 // function onto the stack
4018 static bool get_item_callback(lua_State *L,
4019 const char *name, const char *callbackname)
4021 lua_getglobal(L, "minetest");
4022 lua_getfield(L, -1, "registered_items");
4024 luaL_checktype(L, -1, LUA_TTABLE);
4025 lua_getfield(L, -1, name);
4027 // Should be a table
4028 if(lua_type(L, -1) != LUA_TTABLE)
4030 errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
4034 lua_getfield(L, -1, callbackname);
4036 // Should be a function or nil
4037 if(lua_type(L, -1) == LUA_TFUNCTION)
4041 else if(lua_isnil(L, -1))
4048 errorstream<<"Item \""<<name<<"\" callback \""
4049 <<callbackname<<" is not a function"<<std::endl;
4055 bool scriptapi_item_on_drop(lua_State *L, ItemStack &item,
4056 ServerActiveObject *dropper, v3f pos)
4059 assert(lua_checkstack(L, 20));
4060 StackUnroller stack_unroller(L);
4062 // Push callback function on stack
4063 if(!get_item_callback(L, item.name.c_str(), "on_drop"))
4067 LuaItemStack::create(L, item);
4068 objectref_get_or_create(L, dropper);
4069 pushFloatPos(L, pos);
4070 if(lua_pcall(L, 3, 1, 0))
4071 script_error(L, "error: %s", lua_tostring(L, -1));
4072 if(!lua_isnil(L, -1))
4073 item = read_item(L, -1);
4077 bool scriptapi_item_on_place(lua_State *L, ItemStack &item,
4078 ServerActiveObject *placer, const PointedThing &pointed)
4081 assert(lua_checkstack(L, 20));
4082 StackUnroller stack_unroller(L);
4084 // Push callback function on stack
4085 if(!get_item_callback(L, item.name.c_str(), "on_place"))
4089 LuaItemStack::create(L, item);
4090 objectref_get_or_create(L, placer);
4091 push_pointed_thing(L, pointed);
4092 if(lua_pcall(L, 3, 1, 0))
4093 script_error(L, "error: %s", lua_tostring(L, -1));
4094 if(!lua_isnil(L, -1))
4095 item = read_item(L, -1);
4099 bool scriptapi_item_on_use(lua_State *L, ItemStack &item,
4100 ServerActiveObject *user, const PointedThing &pointed)
4103 assert(lua_checkstack(L, 20));
4104 StackUnroller stack_unroller(L);
4106 // Push callback function on stack
4107 if(!get_item_callback(L, item.name.c_str(), "on_use"))
4111 LuaItemStack::create(L, item);
4112 objectref_get_or_create(L, user);
4113 push_pointed_thing(L, pointed);
4114 if(lua_pcall(L, 3, 1, 0))
4115 script_error(L, "error: %s", lua_tostring(L, -1));
4116 if(!lua_isnil(L, -1))
4117 item = read_item(L, -1);
4121 bool scriptapi_node_on_punch(lua_State *L, v3s16 pos, MapNode node,
4122 ServerActiveObject *puncher)
4125 assert(lua_checkstack(L, 20));
4126 StackUnroller stack_unroller(L);
4128 INodeDefManager *ndef = get_server(L)->ndef();
4130 // Push callback function on stack
4131 if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_punch"))
4136 pushnode(L, node, ndef);
4137 objectref_get_or_create(L, puncher);
4138 if(lua_pcall(L, 3, 0, 0))
4139 script_error(L, "error: %s", lua_tostring(L, -1));
4143 bool scriptapi_node_on_dig(lua_State *L, v3s16 pos, MapNode node,
4144 ServerActiveObject *digger)
4147 assert(lua_checkstack(L, 20));
4148 StackUnroller stack_unroller(L);
4150 INodeDefManager *ndef = get_server(L)->ndef();
4152 // Push callback function on stack
4153 if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_dig"))
4158 pushnode(L, node, ndef);
4159 objectref_get_or_create(L, digger);
4160 if(lua_pcall(L, 3, 0, 0))
4161 script_error(L, "error: %s", lua_tostring(L, -1));
4169 void scriptapi_environment_step(lua_State *L, float dtime)
4172 assert(lua_checkstack(L, 20));
4173 //infostream<<"scriptapi_environment_step"<<std::endl;
4174 StackUnroller stack_unroller(L);
4176 // Get minetest.registered_globalsteps
4177 lua_getglobal(L, "minetest");
4178 lua_getfield(L, -1, "registered_globalsteps");
4179 luaL_checktype(L, -1, LUA_TTABLE);
4180 int table = lua_gettop(L);
4183 while(lua_next(L, table) != 0){
4184 // key at index -2 and value at index -1
4185 luaL_checktype(L, -1, LUA_TFUNCTION);
4187 lua_pushnumber(L, dtime);
4188 if(lua_pcall(L, 1, 0, 0))
4189 script_error(L, "error: %s", lua_tostring(L, -1));
4190 // value removed, keep key for next iteration
4194 void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
4197 assert(lua_checkstack(L, 20));
4198 //infostream<<"scriptapi_environment_on_generated"<<std::endl;
4199 StackUnroller stack_unroller(L);
4201 // Get minetest.registered_on_generateds
4202 lua_getglobal(L, "minetest");
4203 lua_getfield(L, -1, "registered_on_generateds");
4204 luaL_checktype(L, -1, LUA_TTABLE);
4205 int table = lua_gettop(L);
4208 while(lua_next(L, table) != 0){
4209 // key at index -2 and value at index -1
4210 luaL_checktype(L, -1, LUA_TFUNCTION);
4212 push_v3s16(L, minp);
4213 push_v3s16(L, maxp);
4214 if(lua_pcall(L, 2, 0, 0))
4215 script_error(L, "error: %s", lua_tostring(L, -1));
4216 // value removed, keep key for next iteration
4224 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
4225 const std::string &staticdata)
4228 assert(lua_checkstack(L, 20));
4229 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
4230 <<name<<"\""<<std::endl;
4231 StackUnroller stack_unroller(L);
4233 // Get minetest.registered_entities[name]
4234 lua_getglobal(L, "minetest");
4235 lua_getfield(L, -1, "registered_entities");
4236 luaL_checktype(L, -1, LUA_TTABLE);
4237 lua_pushstring(L, name);
4238 lua_gettable(L, -2);
4239 // Should be a table, which we will use as a prototype
4240 //luaL_checktype(L, -1, LUA_TTABLE);
4241 if(lua_type(L, -1) != LUA_TTABLE){
4242 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
4245 int prototype_table = lua_gettop(L);
4246 //dump2(L, "prototype_table");
4248 // Create entity object
4250 int object = lua_gettop(L);
4252 // Set object metatable
4253 lua_pushvalue(L, prototype_table);
4254 lua_setmetatable(L, -2);
4256 // Add object reference
4257 // This should be userdata with metatable ObjectRef
4258 objectref_get(L, id);
4259 luaL_checktype(L, -1, LUA_TUSERDATA);
4260 if(!luaL_checkudata(L, -1, "ObjectRef"))
4261 luaL_typerror(L, -1, "ObjectRef");
4262 lua_setfield(L, -2, "object");
4264 // minetest.luaentities[id] = object
4265 lua_getglobal(L, "minetest");
4266 lua_getfield(L, -1, "luaentities");
4267 luaL_checktype(L, -1, LUA_TTABLE);
4268 lua_pushnumber(L, id); // Push id
4269 lua_pushvalue(L, object); // Copy object to top of stack
4270 lua_settable(L, -3);
4272 // Get on_activate function
4273 lua_pushvalue(L, object);
4274 lua_getfield(L, -1, "on_activate");
4275 if(!lua_isnil(L, -1)){
4276 luaL_checktype(L, -1, LUA_TFUNCTION);
4277 lua_pushvalue(L, object); // self
4278 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
4279 // Call with 2 arguments, 0 results
4280 if(lua_pcall(L, 2, 0, 0))
4281 script_error(L, "error running function %s:on_activate: %s\n",
4282 name, lua_tostring(L, -1));
4288 void scriptapi_luaentity_rm(lua_State *L, u16 id)
4291 assert(lua_checkstack(L, 20));
4292 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
4294 // Get minetest.luaentities table
4295 lua_getglobal(L, "minetest");
4296 lua_getfield(L, -1, "luaentities");
4297 luaL_checktype(L, -1, LUA_TTABLE);
4298 int objectstable = lua_gettop(L);
4300 // Set luaentities[id] = nil
4301 lua_pushnumber(L, id); // Push id
4303 lua_settable(L, objectstable);
4305 lua_pop(L, 2); // pop luaentities, minetest
4308 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
4311 assert(lua_checkstack(L, 20));
4312 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
4313 StackUnroller stack_unroller(L);
4315 // Get minetest.luaentities[id]
4316 luaentity_get(L, id);
4317 int object = lua_gettop(L);
4319 // Get get_staticdata function
4320 lua_pushvalue(L, object);
4321 lua_getfield(L, -1, "get_staticdata");
4322 if(lua_isnil(L, -1))
4325 luaL_checktype(L, -1, LUA_TFUNCTION);
4326 lua_pushvalue(L, object); // self
4327 // Call with 1 arguments, 1 results
4328 if(lua_pcall(L, 1, 1, 0))
4329 script_error(L, "error running function get_staticdata: %s\n",
4330 lua_tostring(L, -1));
4333 const char *s = lua_tolstring(L, -1, &len);
4334 return std::string(s, len);
4337 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
4338 LuaEntityProperties *prop)
4341 assert(lua_checkstack(L, 20));
4342 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
4343 StackUnroller stack_unroller(L);
4345 // Get minetest.luaentities[id]
4346 luaentity_get(L, id);
4347 //int object = lua_gettop(L);
4351 getboolfield(L, -1, "physical", prop->physical);
4353 getfloatfield(L, -1, "weight", prop->weight);
4355 lua_getfield(L, -1, "collisionbox");
4356 if(lua_istable(L, -1))
4357 prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
4360 getstringfield(L, -1, "visual", prop->visual);
4362 lua_getfield(L, -1, "visual_size");
4363 if(lua_istable(L, -1))
4364 prop->visual_size = read_v2f(L, -1);
4367 lua_getfield(L, -1, "textures");
4368 if(lua_istable(L, -1)){
4369 prop->textures.clear();
4370 int table = lua_gettop(L);
4372 while(lua_next(L, table) != 0){
4373 // key at index -2 and value at index -1
4374 if(lua_isstring(L, -1))
4375 prop->textures.push_back(lua_tostring(L, -1));
4377 prop->textures.push_back("");
4378 // removes value, keeps key for next iteration
4384 lua_getfield(L, -1, "spritediv");
4385 if(lua_istable(L, -1))
4386 prop->spritediv = read_v2s16(L, -1);
4389 lua_getfield(L, -1, "initial_sprite_basepos");
4390 if(lua_istable(L, -1))
4391 prop->initial_sprite_basepos = read_v2s16(L, -1);
4395 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
4398 assert(lua_checkstack(L, 20));
4399 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
4400 StackUnroller stack_unroller(L);
4402 // Get minetest.luaentities[id]
4403 luaentity_get(L, id);
4404 int object = lua_gettop(L);
4405 // State: object is at top of stack
4406 // Get step function
4407 lua_getfield(L, -1, "on_step");
4408 if(lua_isnil(L, -1))
4410 luaL_checktype(L, -1, LUA_TFUNCTION);
4411 lua_pushvalue(L, object); // self
4412 lua_pushnumber(L, dtime); // dtime
4413 // Call with 2 arguments, 0 results
4414 if(lua_pcall(L, 2, 0, 0))
4415 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
4418 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
4419 void scriptapi_luaentity_punch(lua_State *L, u16 id,
4420 ServerActiveObject *puncher, float time_from_last_punch)
4423 assert(lua_checkstack(L, 20));
4424 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
4425 StackUnroller stack_unroller(L);
4427 // Get minetest.luaentities[id]
4428 luaentity_get(L, id);
4429 int object = lua_gettop(L);
4430 // State: object is at top of stack
4432 lua_getfield(L, -1, "on_punch");
4433 if(lua_isnil(L, -1))
4435 luaL_checktype(L, -1, LUA_TFUNCTION);
4436 lua_pushvalue(L, object); // self
4437 objectref_get_or_create(L, puncher); // Clicker reference
4438 lua_pushnumber(L, time_from_last_punch);
4439 // Call with 2 arguments, 0 results
4440 if(lua_pcall(L, 3, 0, 0))
4441 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
4444 // Calls entity:on_rightclick(ObjectRef clicker)
4445 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
4446 ServerActiveObject *clicker)
4449 assert(lua_checkstack(L, 20));
4450 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
4451 StackUnroller stack_unroller(L);
4453 // Get minetest.luaentities[id]
4454 luaentity_get(L, id);
4455 int object = lua_gettop(L);
4456 // State: object is at top of stack
4458 lua_getfield(L, -1, "on_rightclick");
4459 if(lua_isnil(L, -1))
4461 luaL_checktype(L, -1, LUA_TFUNCTION);
4462 lua_pushvalue(L, object); // self
4463 objectref_get_or_create(L, clicker); // Clicker reference
4464 // Call with 2 arguments, 0 results
4465 if(lua_pcall(L, 2, 0, 0))
4466 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));