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"
33 #include "serverobject.h"
36 #include "luaentity_common.h"
37 #include "content_sao.h" // For LuaEntitySAO
45 - Random node triggers (like grass growth)
46 - Deterministic node triggers (like falling sand)
47 - Object visual client-side stuff
49 - Spritesheets and animation
51 blockdef.metadata_name =
58 - Stores an inventory and stuff in a Settings object
59 meta.inventory_add_list("main")
60 blockdef.on_inventory_modified
61 meta.set("owner", playername)
63 - Item definition (actually, only CraftItem)
64 - (not scripting) Putting items in node metadata (virtual)
67 static void stackDump(lua_State *L, std::ostream &o)
70 int top = lua_gettop(L);
71 for (i = 1; i <= top; i++) { /* repeat for each level */
72 int t = lua_type(L, i);
75 case LUA_TSTRING: /* strings */
76 o<<"\""<<lua_tostring(L, i)<<"\"";
79 case LUA_TBOOLEAN: /* booleans */
80 o<<(lua_toboolean(L, i) ? "true" : "false");
83 case LUA_TNUMBER: /* numbers */ {
85 snprintf(buf, 10, "%g", lua_tonumber(L, i));
89 default: /* other values */
90 o<<lua_typename(L, t);
99 static void realitycheck(lua_State *L)
101 int top = lua_gettop(L);
103 dstream<<"Stack is over 30:"<<std::endl;
104 stackDump(L, dstream);
105 script_error(L, "Stack is over 30 (reality check)");
115 StackUnroller(lua_State *L):
119 m_original_top = lua_gettop(m_lua); // store stack height
123 lua_settop(m_lua, m_original_top); // restore stack height
127 static v3f readFloatPos(lua_State *L, int index)
130 luaL_checktype(L, index, LUA_TTABLE);
131 lua_getfield(L, index, "x");
132 pos.X = lua_tonumber(L, -1);
134 lua_getfield(L, index, "y");
135 pos.Y = lua_tonumber(L, -1);
137 lua_getfield(L, index, "z");
138 pos.Z = lua_tonumber(L, -1);
140 pos *= BS; // Scale to internal format
144 static void pushpos(lua_State *L, v3s16 p)
147 lua_pushnumber(L, p.X);
148 lua_setfield(L, -2, "x");
149 lua_pushnumber(L, p.Y);
150 lua_setfield(L, -2, "y");
151 lua_pushnumber(L, p.Z);
152 lua_setfield(L, -2, "z");
155 static v3s16 readpos(lua_State *L, int index)
157 // Correct rounding at <0
158 v3f pf = readFloatPos(L, index);
159 return floatToInt(pf, BS);
162 static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
165 lua_pushstring(L, ndef->get(n).name.c_str());
166 lua_setfield(L, -2, "name");
167 lua_pushnumber(L, n.getParam1());
168 lua_setfield(L, -2, "param1");
169 lua_pushnumber(L, n.getParam2());
170 lua_setfield(L, -2, "param2");
173 static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
175 lua_getfield(L, index, "name");
176 const char *name = lua_tostring(L, -1);
179 lua_getfield(L, index, "param1");
183 param1 = lua_tonumber(L, -1);
186 lua_getfield(L, index, "param2");
190 param2 = lua_tonumber(L, -1);
192 return MapNode(ndef, name, param1, param2);
195 static video::SColor readARGB8(lua_State *L, int index)
198 luaL_checktype(L, index, LUA_TTABLE);
199 lua_getfield(L, index, "a");
200 if(lua_isnumber(L, -1))
201 color.setAlpha(lua_tonumber(L, -1));
203 lua_getfield(L, index, "r");
204 color.setRed(lua_tonumber(L, -1));
206 lua_getfield(L, index, "g");
207 color.setGreen(lua_tonumber(L, -1));
209 lua_getfield(L, index, "b");
210 color.setBlue(lua_tonumber(L, -1));
215 static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index)
217 core::aabbox3d<f32> box;
218 if(lua_istable(L, -1)){
219 lua_rawgeti(L, -1, 1);
220 box.MinEdge.X = lua_tonumber(L, -1);
222 lua_rawgeti(L, -1, 2);
223 box.MinEdge.Y = lua_tonumber(L, -1);
225 lua_rawgeti(L, -1, 3);
226 box.MinEdge.Z = lua_tonumber(L, -1);
228 lua_rawgeti(L, -1, 4);
229 box.MaxEdge.X = lua_tonumber(L, -1);
231 lua_rawgeti(L, -1, 5);
232 box.MaxEdge.Y = lua_tonumber(L, -1);
234 lua_rawgeti(L, -1, 6);
235 box.MaxEdge.Z = lua_tonumber(L, -1);
241 static bool getstringfield(lua_State *L, int table,
242 const char *fieldname, std::string &result)
244 lua_getfield(L, table, fieldname);
246 if(lua_isstring(L, -1)){
247 result = lua_tostring(L, -1);
254 static bool getintfield(lua_State *L, int table,
255 const char *fieldname, int &result)
257 lua_getfield(L, table, fieldname);
259 if(lua_isnumber(L, -1)){
260 result = lua_tonumber(L, -1);
267 static bool getfloatfield(lua_State *L, int table,
268 const char *fieldname, float &result)
270 lua_getfield(L, table, fieldname);
272 if(lua_isnumber(L, -1)){
273 result = lua_tonumber(L, -1);
280 static bool getboolfield(lua_State *L, int table,
281 const char *fieldname, bool &result)
283 lua_getfield(L, table, fieldname);
285 if(lua_isboolean(L, -1)){
286 result = lua_toboolean(L, -1);
293 static std::string getstringfield_default(lua_State *L, int table,
294 const char *fieldname, const std::string &default_)
296 std::string result = default_;
297 getstringfield(L, table, fieldname, result);
301 static int getintfield_default(lua_State *L, int table,
302 const char *fieldname, int default_)
304 int result = default_;
305 getintfield(L, table, fieldname, result);
309 static bool getboolfield_default(lua_State *L, int table,
310 const char *fieldname, bool default_)
312 bool result = default_;
313 getboolfield(L, table, fieldname, result);
323 static bool string_to_enum(const EnumString *spec, int &result,
324 const std::string &str)
326 const EnumString *esp = spec;
328 if(str == std::string(esp->str)){
337 /*static bool enum_to_string(const EnumString *spec, std::string &result,
340 const EnumString *esp = spec;
351 static int getenumfield(lua_State *L, int table,
352 const char *fieldname, const EnumString *spec, int default_)
354 int result = default_;
355 string_to_enum(spec, result,
356 getstringfield_default(L, table, fieldname, ""));
360 struct EnumString es_DrawType[] =
362 {NDT_NORMAL, "normal"},
363 {NDT_AIRLIKE, "airlike"},
364 {NDT_LIQUID, "liquid"},
365 {NDT_FLOWINGLIQUID, "flowingliquid"},
366 {NDT_GLASSLIKE, "glasslike"},
367 {NDT_ALLFACES, "allfaces"},
368 {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
369 {NDT_TORCHLIKE, "torchlike"},
370 {NDT_SIGNLIKE, "signlike"},
371 {NDT_PLANTLIKE, "plantlike"},
372 {NDT_FENCELIKE, "fencelike"},
373 {NDT_RAILLIKE, "raillike"},
377 struct EnumString es_ContentParamType[] =
380 {CPT_LIGHT, "light"},
381 {CPT_MINERAL, "mineral"},
382 {CPT_FACEDIR_SIMPLE, "facedir_simple"},
385 struct EnumString es_LiquidType[] =
387 {LIQUID_NONE, "none"},
388 {LIQUID_FLOWING, "flowing"},
389 {LIQUID_SOURCE, "source"},
392 struct EnumString es_NodeBoxType[] =
394 {NODEBOX_REGULAR, "regular"},
395 {NODEBOX_FIXED, "fixed"},
396 {NODEBOX_WALLMOUNTED, "wallmounted"},
399 struct EnumString es_Diggability[] =
401 {DIGGABLE_NOT, "not"},
402 {DIGGABLE_NORMAL, "normal"},
403 {DIGGABLE_CONSTANT, "constant"},
410 // Register new object prototype
411 // register_entity(name, prototype)
412 static int l_register_entity(lua_State *L)
414 const char *name = luaL_checkstring(L, 1);
415 infostream<<"register_entity: "<<name<<std::endl;
416 luaL_checktype(L, 2, LUA_TTABLE);
418 // Get minetest.registered_entities
419 lua_getglobal(L, "minetest");
420 lua_getfield(L, -1, "registered_entities");
421 luaL_checktype(L, -1, LUA_TTABLE);
422 int registered_entities = lua_gettop(L);
423 lua_pushvalue(L, 2); // Object = param 2 -> stack top
424 // registered_entities[name] = object
425 lua_setfield(L, registered_entities, name);
427 // Get registered object to top of stack
430 // Set __index to point to itself
431 lua_pushvalue(L, -1);
432 lua_setfield(L, -2, "__index");
434 // Set metatable.__index = metatable
435 luaL_getmetatable(L, "minetest.entity");
436 lua_pushvalue(L, -1); // duplicate metatable
437 lua_setfield(L, -2, "__index");
438 // Set object metatable
439 lua_setmetatable(L, -2);
441 return 0; /* number of results */
444 // register_tool(name, {lots of stuff})
445 static int l_register_tool(lua_State *L)
447 const char *name = luaL_checkstring(L, 1);
448 infostream<<"register_tool: "<<name<<std::endl;
449 luaL_checktype(L, 2, LUA_TTABLE);
452 // Get server from registry
453 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
454 Server *server = (Server*)lua_touserdata(L, -1);
455 // And get the writable tool definition manager from the server
456 IWritableToolDefManager *tooldef =
457 server->getWritableToolDefManager();
461 getstringfield(L, table, "image", def.imagename);
462 getfloatfield(L, table, "basetime", def.properties.basetime);
463 getfloatfield(L, table, "dt_weight", def.properties.dt_weight);
464 getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness);
465 getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness);
466 getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability);
467 getfloatfield(L, table, "basedurability", def.properties.basedurability);
468 getfloatfield(L, table, "dd_weight", def.properties.dd_weight);
469 getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness);
470 getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness);
471 getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability);
473 tooldef->registerTool(name, def);
474 return 0; /* number of results */
477 // register_node(name, {lots of stuff})
478 static int l_register_node(lua_State *L)
480 const char *name = luaL_checkstring(L, 1);
481 infostream<<"register_node: "<<name<<std::endl;
482 luaL_checktype(L, 2, LUA_TTABLE);
485 // Get server from registry
486 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
487 Server *server = (Server*)lua_touserdata(L, -1);
488 // And get the writable node definition manager from the server
489 IWritableNodeDefManager *nodedef =
490 server->getWritableNodeDefManager();
498 // Default to getting the corresponding NodeItem when dug
499 f.dug_item = std::string("NodeItem \"")+name+"\" 1";
501 // Default to unknown_block.png as all textures
502 f.setAllTextures("unknown_block.png");
505 Read definiton from Lua
510 /* Visual definition */
512 f.drawtype = (NodeDrawType)getenumfield(L, table0, "drawtype", es_DrawType,
514 getfloatfield(L, table0, "visual_scale", f.visual_scale);
516 lua_getfield(L, table0, "tile_images");
517 if(lua_istable(L, -1)){
518 int table = lua_gettop(L);
521 while(lua_next(L, table) != 0){
522 // key at index -2 and value at index -1
523 if(lua_isstring(L, -1))
524 f.tname_tiles[i] = lua_tostring(L, -1);
526 f.tname_tiles[i] = "";
527 // removes value, keeps key for next iteration
535 // Copy last value to all remaining textures
537 std::string lastname = f.tname_tiles[i-1];
539 f.tname_tiles[i] = lastname;
546 getstringfield(L, table0, "inventory_image", f.tname_inventory);
548 lua_getfield(L, table0, "special_materials");
549 if(lua_istable(L, -1)){
550 int table = lua_gettop(L);
553 while(lua_next(L, table) != 0){
554 // key at index -2 and value at index -1
555 int smtable = lua_gettop(L);
556 std::string tname = getstringfield_default(
557 L, smtable, "image", "");
558 bool backface_culling = getboolfield_default(
559 L, smtable, "backface_culling", true);
560 MaterialSpec mspec(tname, backface_culling);
561 f.setSpecialMaterial(i, mspec);
562 // removes value, keeps key for next iteration
573 f.alpha = getintfield_default(L, table0, "alpha", 255);
577 lua_getfield(L, table0, "post_effect_color");
578 if(!lua_isnil(L, -1))
579 f.post_effect_color = readARGB8(L, -1);
582 f.param_type = (ContentParamType)getenumfield(L, table0, "paramtype",
583 es_ContentParamType, CPT_NONE);
585 // True for all ground-like things like stone and mud, false for eg. trees
586 getboolfield(L, table0, "is_ground_content", f.is_ground_content);
587 getboolfield(L, table0, "light_propagates", f.light_propagates);
588 getboolfield(L, table0, "sunlight_propagates", f.sunlight_propagates);
589 // This is used for collision detection.
590 // Also for general solidness queries.
591 getboolfield(L, table0, "walkable", f.walkable);
592 // Player can point to these
593 getboolfield(L, table0, "pointable", f.pointable);
594 // Player can dig these
595 getboolfield(L, table0, "diggable", f.diggable);
596 // Player can climb these
597 getboolfield(L, table0, "climbable", f.climbable);
598 // Player can build on these
599 getboolfield(L, table0, "buildable_to", f.buildable_to);
600 // If true, param2 is set to direction when placed. Used for torches.
601 // NOTE: the direction format is quite inefficient and should be changed
602 getboolfield(L, table0, "wall_mounted", f.wall_mounted);
603 // If true, node is equivalent to air. Torches are, air is. Water is not.
604 // Is used for example to check whether a mud block can have grass on.
605 getboolfield(L, table0, "air_equivalent", f.air_equivalent);
606 // Whether this content type often contains mineral.
607 // Used for texture atlas creation.
608 // Currently only enabled for CONTENT_STONE.
609 getboolfield(L, table0, "often_contains_mineral", f.often_contains_mineral);
610 // Inventory item string as which the node appears in inventory when dug.
611 // Mineral overrides this.
612 getstringfield(L, table0, "dug_item", f.dug_item);
613 // Extra dug item and its rarity
614 getstringfield(L, table0, "extra_dug_item", f.extra_dug_item);
615 // Usual get interval for extra dug item
616 getintfield(L, table0, "extra_dug_item_rarity", f.extra_dug_item_rarity);
617 // Metadata name of node (eg. "furnace")
618 getstringfield(L, table0, "metadata_name", f.metadata_name);
619 // Whether the node is non-liquid, source liquid or flowing liquid
620 f.liquid_type = (LiquidType)getenumfield(L, table0, "liquidtype",
621 es_LiquidType, LIQUID_NONE);
622 // If the content is liquid, this is the flowing version of the liquid.
623 getstringfield(L, table0, "liquid_alternative_flowing",
624 f.liquid_alternative_flowing);
625 // If the content is liquid, this is the source version of the liquid.
626 getstringfield(L, table0, "liquid_alternative_source",
627 f.liquid_alternative_source);
628 // Viscosity for fluid flow, ranging from 1 to 7, with
629 // 1 giving almost instantaneous propagation and 7 being
630 // the slowest possible
631 f.liquid_viscosity = getintfield_default(L, table0,
632 "liquid_viscosity", f.liquid_viscosity);
633 // Amount of light the node emits
634 f.light_source = getintfield_default(L, table0,
635 "light_source", f.light_source);
636 f.damage_per_second = getintfield_default(L, table0,
637 "damage_per_second", f.damage_per_second);
639 lua_getfield(L, table0, "selection_box");
640 if(lua_istable(L, -1)){
641 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
642 es_NodeBoxType, NODEBOX_REGULAR);
644 lua_getfield(L, -1, "fixed");
645 if(lua_istable(L, -1))
646 f.selection_box.fixed = read_aabbox3df32(L, -1);
649 lua_getfield(L, -1, "wall_top");
650 if(lua_istable(L, -1))
651 f.selection_box.wall_top = read_aabbox3df32(L, -1);
654 lua_getfield(L, -1, "wall_bottom");
655 if(lua_istable(L, -1))
656 f.selection_box.wall_bottom = read_aabbox3df32(L, -1);
659 lua_getfield(L, -1, "wall_side");
660 if(lua_istable(L, -1))
661 f.selection_box.wall_side = read_aabbox3df32(L, -1);
666 lua_getfield(L, table0, "material");
667 if(lua_istable(L, -1)){
668 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
669 es_Diggability, DIGGABLE_NORMAL);
671 getfloatfield(L, -1, "constant_time", f.material.constant_time);
672 getfloatfield(L, -1, "weight", f.material.weight);
673 getfloatfield(L, -1, "crackiness", f.material.crackiness);
674 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
675 getfloatfield(L, -1, "cuttability", f.material.cuttability);
676 getfloatfield(L, -1, "flammability", f.material.flammability);
680 getstringfield(L, table0, "cookresult_item", f.cookresult_item);
681 getfloatfield(L, table0, "furnace_cooktime", f.furnace_cooktime);
682 getfloatfield(L, table0, "furnace_burntime", f.furnace_burntime);
688 nodedef->set(name, f);
690 return 0; /* number of results */
693 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
694 static int l_register_craft(lua_State *L)
696 infostream<<"register_craft"<<std::endl;
697 luaL_checktype(L, 1, LUA_TTABLE);
700 // Get server from registry
701 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
702 Server *server = (Server*)lua_touserdata(L, -1);
703 // And get the writable craft definition manager from the server
704 IWritableCraftDefManager *craftdef =
705 server->getWritableCraftDefManager();
709 std::vector<std::string> input;
711 lua_getfield(L, table0, "output");
712 luaL_checktype(L, -1, LUA_TSTRING);
713 if(lua_isstring(L, -1))
714 output = lua_tostring(L, -1);
717 lua_getfield(L, table0, "recipe");
718 luaL_checktype(L, -1, LUA_TTABLE);
719 if(lua_istable(L, -1)){
720 int table1 = lua_gettop(L);
723 while(lua_next(L, table1) != 0){
725 // key at index -2 and value at index -1
726 luaL_checktype(L, -1, LUA_TTABLE);
727 if(lua_istable(L, -1)){
728 int table2 = lua_gettop(L);
730 while(lua_next(L, table2) != 0){
731 // key at index -2 and value at index -1
732 luaL_checktype(L, -1, LUA_TSTRING);
733 input.push_back(lua_tostring(L, -1));
734 // removes value, keeps key for next iteration
742 if(colcount != width){
743 script_error(L, "error: %s\n", "Invalid crafting recipe");
746 // removes value, keeps key for next iteration
753 CraftDefinition def(output, width, input);
754 craftdef->registerCraft(def);
756 return 0; /* number of results */
759 static int register_lua_callback(lua_State *L, const char *tablename)
761 luaL_checktype(L, 1, LUA_TFUNCTION);
763 lua_getglobal(L, "table");
764 lua_getfield(L, -1, "insert");
765 int table_insert = lua_gettop(L);
766 // Get minetest.registered_globalsteps
767 lua_getglobal(L, "minetest");
768 lua_getfield(L, -1, tablename);
769 luaL_checktype(L, -1, LUA_TTABLE);
770 int registered = lua_gettop(L);
771 // table.insert(registered_globalsteps, func)
772 lua_pushvalue(L, table_insert);
773 lua_pushvalue(L, registered);
774 lua_pushvalue(L, 1); // push function from argument 1
776 if(lua_pcall(L, 2, 0, 0))
777 script_error(L, "error: %s\n", lua_tostring(L, -1));
779 return 0; /* number of results */
782 // Register a global step function
783 // register_globalstep(function)
784 static int l_register_globalstep(lua_State *L)
786 infostream<<"register_globalstep"<<std::endl;
787 return register_lua_callback(L, "registered_globalsteps");
790 // register_on_placenode(function)
791 static int l_register_on_placenode(lua_State *L)
793 infostream<<"register_on_placenode"<<std::endl;
794 return register_lua_callback(L, "registered_on_placenodes");
797 // register_on_dignode(function)
798 static int l_register_on_dignode(lua_State *L)
800 infostream<<"register_on_dignode"<<std::endl;
801 return register_lua_callback(L, "registered_on_dignodes");
804 // register_on_punchnode(function)
805 static int l_register_on_punchnode(lua_State *L)
807 infostream<<"register_on_punchnode"<<std::endl;
808 return register_lua_callback(L, "registered_on_punchnodes");
811 static const struct luaL_Reg minetest_f [] = {
812 {"register_entity", l_register_entity},
813 {"register_tool", l_register_tool},
814 {"register_node", l_register_node},
815 {"register_craft", l_register_craft},
816 {"register_globalstep", l_register_globalstep},
817 {"register_on_placenode", l_register_on_placenode},
818 {"register_on_dignode", l_register_on_dignode},
819 {"register_on_punchnode", l_register_on_punchnode},
827 static const struct luaL_Reg minetest_entity_m [] = {
832 Getters for stuff in main tables
835 static void objectref_get(lua_State *L, u16 id)
837 // Get minetest.object_refs[i]
838 lua_getglobal(L, "minetest");
839 lua_getfield(L, -1, "object_refs");
840 luaL_checktype(L, -1, LUA_TTABLE);
841 lua_pushnumber(L, id);
843 lua_remove(L, -2); // object_refs
844 lua_remove(L, -2); // minetest
847 static void luaentity_get(lua_State *L, u16 id)
849 // Get minetest.luaentities[i]
850 lua_getglobal(L, "minetest");
851 lua_getfield(L, -1, "luaentities");
852 luaL_checktype(L, -1, LUA_TTABLE);
853 lua_pushnumber(L, id);
855 lua_remove(L, -2); // luaentities
856 lua_remove(L, -2); // minetest
862 #define method(class, name) {#name, class::l_##name}
867 ServerEnvironment *m_env;
869 static const char className[];
870 static const luaL_reg methods[];
872 static EnvRef *checkobject(lua_State *L, int narg)
874 luaL_checktype(L, narg, LUA_TUSERDATA);
875 void *ud = luaL_checkudata(L, narg, className);
876 if(!ud) luaL_typerror(L, narg, className);
877 return *(EnvRef**)ud; // unbox pointer
880 // Exported functions
882 // EnvRef:add_node(pos, node)
883 // pos = {x=num, y=num, z=num}
884 static int l_add_node(lua_State *L)
886 infostream<<"EnvRef::l_add_node()"<<std::endl;
887 EnvRef *o = checkobject(L, 1);
888 ServerEnvironment *env = o->m_env;
889 if(env == NULL) return 0;
891 v3s16 pos = readpos(L, 2);
893 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
895 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
896 lua_pushboolean(L, succeeded);
900 // EnvRef:remove_node(pos)
901 // pos = {x=num, y=num, z=num}
902 static int l_remove_node(lua_State *L)
904 infostream<<"EnvRef::l_remove_node()"<<std::endl;
905 EnvRef *o = checkobject(L, 1);
906 ServerEnvironment *env = o->m_env;
907 if(env == NULL) return 0;
909 v3s16 pos = readpos(L, 2);
911 bool succeeded = env->getMap().removeNodeWithEvent(pos);
912 lua_pushboolean(L, succeeded);
916 // EnvRef:get_node(pos)
917 // pos = {x=num, y=num, z=num}
918 static int l_get_node(lua_State *L)
920 infostream<<"EnvRef::l_get_node()"<<std::endl;
921 EnvRef *o = checkobject(L, 1);
922 ServerEnvironment *env = o->m_env;
923 if(env == NULL) return 0;
925 v3s16 pos = readpos(L, 2);
927 MapNode n = env->getMap().getNodeNoEx(pos);
929 pushnode(L, n, env->getGameDef()->ndef());
933 // EnvRef:add_luaentity(pos, entityname)
934 // pos = {x=num, y=num, z=num}
935 static int l_add_luaentity(lua_State *L)
937 infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
938 EnvRef *o = checkobject(L, 1);
939 ServerEnvironment *env = o->m_env;
940 if(env == NULL) return 0;
942 v3f pos = readFloatPos(L, 2);
944 const char *name = lua_tostring(L, 3);
946 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
947 env->addActiveObject(obj);
951 static int gc_object(lua_State *L) {
952 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
958 EnvRef(ServerEnvironment *env):
961 infostream<<"EnvRef created"<<std::endl;
966 infostream<<"EnvRef destructing"<<std::endl;
969 // Creates an EnvRef and leaves it on top of stack
970 // Not callable from Lua; all references are created on the C side.
971 static void create(lua_State *L, ServerEnvironment *env)
973 EnvRef *o = new EnvRef(env);
974 //infostream<<"EnvRef::create: o="<<o<<std::endl;
975 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
976 luaL_getmetatable(L, className);
977 lua_setmetatable(L, -2);
980 static void set_null(lua_State *L)
982 EnvRef *o = checkobject(L, -1);
986 static void Register(lua_State *L)
989 int methodtable = lua_gettop(L);
990 luaL_newmetatable(L, className);
991 int metatable = lua_gettop(L);
993 lua_pushliteral(L, "__metatable");
994 lua_pushvalue(L, methodtable);
995 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
997 lua_pushliteral(L, "__index");
998 lua_pushvalue(L, methodtable);
999 lua_settable(L, metatable);
1001 lua_pushliteral(L, "__gc");
1002 lua_pushcfunction(L, gc_object);
1003 lua_settable(L, metatable);
1005 lua_pop(L, 1); // drop metatable
1007 luaL_openlib(L, 0, methods, 0); // fill methodtable
1008 lua_pop(L, 1); // drop methodtable
1010 // Cannot be created from Lua
1011 //lua_register(L, className, create_object);
1014 const char EnvRef::className[] = "EnvRef";
1015 const luaL_reg EnvRef::methods[] = {
1016 method(EnvRef, add_node),
1017 method(EnvRef, remove_node),
1018 method(EnvRef, get_node),
1019 method(EnvRef, add_luaentity),
1026 ServerActiveObject *m_object;
1028 static const char className[];
1029 static const luaL_reg methods[];
1031 static ObjectRef *checkobject(lua_State *L, int narg)
1033 luaL_checktype(L, narg, LUA_TUSERDATA);
1034 void *ud = luaL_checkudata(L, narg, className);
1035 if(!ud) luaL_typerror(L, narg, className);
1036 return *(ObjectRef**)ud; // unbox pointer
1039 static ServerActiveObject* getobject(ObjectRef *ref)
1041 ServerActiveObject *co = ref->m_object;
1045 static LuaEntitySAO* getluaobject(ObjectRef *ref)
1047 ServerActiveObject *obj = getobject(ref);
1050 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1052 return (LuaEntitySAO*)obj;
1055 // Exported functions
1057 // garbage collector
1058 static int gc_object(lua_State *L) {
1059 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1060 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1066 static int l_remove(lua_State *L)
1068 ObjectRef *ref = checkobject(L, 1);
1069 ServerActiveObject *co = getobject(ref);
1070 if(co == NULL) return 0;
1071 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1072 co->m_removed = true;
1077 // returns: {x=num, y=num, z=num}
1078 static int l_getpos(lua_State *L)
1080 ObjectRef *ref = checkobject(L, 1);
1081 ServerActiveObject *co = getobject(ref);
1082 if(co == NULL) return 0;
1083 v3f pos = co->getBasePosition() / BS;
1085 lua_pushnumber(L, pos.X);
1086 lua_setfield(L, -2, "x");
1087 lua_pushnumber(L, pos.Y);
1088 lua_setfield(L, -2, "y");
1089 lua_pushnumber(L, pos.Z);
1090 lua_setfield(L, -2, "z");
1094 // setpos(self, pos)
1095 static int l_setpos(lua_State *L)
1097 ObjectRef *ref = checkobject(L, 1);
1098 //LuaEntitySAO *co = getluaobject(ref);
1099 ServerActiveObject *co = getobject(ref);
1100 if(co == NULL) return 0;
1102 v3f pos = readFloatPos(L, 2);
1108 // moveto(self, pos, continuous=false)
1109 static int l_moveto(lua_State *L)
1111 ObjectRef *ref = checkobject(L, 1);
1112 //LuaEntitySAO *co = getluaobject(ref);
1113 ServerActiveObject *co = getobject(ref);
1114 if(co == NULL) return 0;
1116 v3f pos = readFloatPos(L, 2);
1118 bool continuous = lua_toboolean(L, 3);
1120 co->moveTo(pos, continuous);
1124 // setvelocity(self, velocity)
1125 static int l_setvelocity(lua_State *L)
1127 ObjectRef *ref = checkobject(L, 1);
1128 LuaEntitySAO *co = getluaobject(ref);
1129 if(co == NULL) return 0;
1131 v3f pos = readFloatPos(L, 2);
1133 co->setVelocity(pos);
1137 // setacceleration(self, acceleration)
1138 static int l_setacceleration(lua_State *L)
1140 ObjectRef *ref = checkobject(L, 1);
1141 LuaEntitySAO *co = getluaobject(ref);
1142 if(co == NULL) return 0;
1144 v3f pos = readFloatPos(L, 2);
1146 co->setAcceleration(pos);
1150 // add_to_inventory(self, itemstring)
1151 // returns: true if item was added, false otherwise
1152 static int l_add_to_inventory(lua_State *L)
1154 ObjectRef *ref = checkobject(L, 1);
1155 luaL_checkstring(L, 2);
1156 ServerActiveObject *co = getobject(ref);
1157 if(co == NULL) return 0;
1159 const char *itemstring = lua_tostring(L, 2);
1160 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1161 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1163 std::istringstream is(itemstring, std::ios::binary);
1164 ServerEnvironment *env = co->getEnv();
1166 IGameDef *gamedef = env->getGameDef();
1167 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1168 infostream<<"item="<<env<<std::endl;
1169 bool fits = co->addToInventory(item);
1171 lua_pushboolean(L, fits);
1176 ObjectRef(ServerActiveObject *object):
1179 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1185 infostream<<"ObjectRef destructing for id="
1186 <<m_object->getId()<<std::endl;
1188 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1191 // Creates an ObjectRef and leaves it on top of stack
1192 // Not callable from Lua; all references are created on the C side.
1193 static void create(lua_State *L, ServerActiveObject *object)
1195 ObjectRef *o = new ObjectRef(object);
1196 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1197 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1198 luaL_getmetatable(L, className);
1199 lua_setmetatable(L, -2);
1202 static void set_null(lua_State *L)
1204 ObjectRef *o = checkobject(L, -1);
1208 static void Register(lua_State *L)
1211 int methodtable = lua_gettop(L);
1212 luaL_newmetatable(L, className);
1213 int metatable = lua_gettop(L);
1215 lua_pushliteral(L, "__metatable");
1216 lua_pushvalue(L, methodtable);
1217 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1219 lua_pushliteral(L, "__index");
1220 lua_pushvalue(L, methodtable);
1221 lua_settable(L, metatable);
1223 lua_pushliteral(L, "__gc");
1224 lua_pushcfunction(L, gc_object);
1225 lua_settable(L, metatable);
1227 lua_pop(L, 1); // drop metatable
1229 luaL_openlib(L, 0, methods, 0); // fill methodtable
1230 lua_pop(L, 1); // drop methodtable
1232 // Cannot be created from Lua
1233 //lua_register(L, className, create_object);
1236 const char ObjectRef::className[] = "ObjectRef";
1237 const luaL_reg ObjectRef::methods[] = {
1238 method(ObjectRef, remove),
1239 method(ObjectRef, getpos),
1240 method(ObjectRef, setpos),
1241 method(ObjectRef, moveto),
1242 method(ObjectRef, setvelocity),
1243 method(ObjectRef, setacceleration),
1244 method(ObjectRef, add_to_inventory),
1248 // Creates a new anonymous reference if id=0
1249 static void objectref_get_or_create(lua_State *L,
1250 ServerActiveObject *cobj)
1252 if(cobj->getId() == 0){
1253 ObjectRef::create(L, cobj);
1255 objectref_get(L, cobj->getId());
1260 Main export function
1263 void scriptapi_export(lua_State *L, Server *server)
1266 assert(lua_checkstack(L, 20));
1267 infostream<<"scriptapi_export"<<std::endl;
1268 StackUnroller stack_unroller(L);
1270 // Store server as light userdata in registry
1271 lua_pushlightuserdata(L, server);
1272 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
1274 // Register global functions in table minetest
1276 luaL_register(L, NULL, minetest_f);
1277 lua_setglobal(L, "minetest");
1279 // Get the main minetest table
1280 lua_getglobal(L, "minetest");
1282 // Add tables to minetest
1285 lua_setfield(L, -2, "registered_blocks");*/
1288 lua_setfield(L, -2, "registered_entities");
1291 lua_setfield(L, -2, "registered_globalsteps");
1294 lua_setfield(L, -2, "registered_on_placenodes");
1297 lua_setfield(L, -2, "registered_on_dignodes");
1300 lua_setfield(L, -2, "registered_on_punchnodes");
1303 lua_setfield(L, -2, "object_refs");
1306 lua_setfield(L, -2, "luaentities");
1308 // Create entity prototype
1309 luaL_newmetatable(L, "minetest.entity");
1310 // metatable.__index = metatable
1311 lua_pushvalue(L, -1); // Duplicate metatable
1312 lua_setfield(L, -2, "__index");
1313 // Put functions in metatable
1314 luaL_register(L, NULL, minetest_entity_m);
1315 // Put other stuff in metatable
1317 // Environment C reference
1318 EnvRef::Register(L);
1320 // Object C reference
1321 ObjectRef::Register(L);
1324 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
1327 assert(lua_checkstack(L, 20));
1328 infostream<<"scriptapi_add_environment"<<std::endl;
1329 StackUnroller stack_unroller(L);
1331 // Create EnvRef on stack
1332 EnvRef::create(L, env);
1333 int envref = lua_gettop(L);
1335 // minetest.env = envref
1336 lua_getglobal(L, "minetest");
1337 luaL_checktype(L, -1, LUA_TTABLE);
1338 lua_pushvalue(L, envref);
1339 lua_setfield(L, -2, "env");
1343 // Dump stack top with the dump2 function
1344 static void dump2(lua_State *L, const char *name)
1346 // Dump object (debug)
1347 lua_getglobal(L, "dump2");
1348 luaL_checktype(L, -1, LUA_TFUNCTION);
1349 lua_pushvalue(L, -2); // Get previous stack top as first parameter
1350 lua_pushstring(L, name);
1351 if(lua_pcall(L, 2, 0, 0))
1352 script_error(L, "error: %s\n", lua_tostring(L, -1));
1360 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1363 assert(lua_checkstack(L, 20));
1364 infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1365 StackUnroller stack_unroller(L);
1367 // Create object on stack
1368 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1369 int object = lua_gettop(L);
1371 // Get minetest.object_refs table
1372 lua_getglobal(L, "minetest");
1373 lua_getfield(L, -1, "object_refs");
1374 luaL_checktype(L, -1, LUA_TTABLE);
1375 int objectstable = lua_gettop(L);
1377 // object_refs[id] = object
1378 lua_pushnumber(L, cobj->getId()); // Push id
1379 lua_pushvalue(L, object); // Copy object to top of stack
1380 lua_settable(L, objectstable);
1383 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1386 assert(lua_checkstack(L, 20));
1387 infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1388 StackUnroller stack_unroller(L);
1390 // Get minetest.object_refs table
1391 lua_getglobal(L, "minetest");
1392 lua_getfield(L, -1, "object_refs");
1393 luaL_checktype(L, -1, LUA_TTABLE);
1394 int objectstable = lua_gettop(L);
1396 // Get object_refs[id]
1397 lua_pushnumber(L, cobj->getId()); // Push id
1398 lua_gettable(L, objectstable);
1399 // Set object reference to NULL
1400 ObjectRef::set_null(L);
1401 lua_pop(L, 1); // pop object
1403 // Set object_refs[id] = nil
1404 lua_pushnumber(L, cobj->getId()); // Push id
1406 lua_settable(L, objectstable);
1413 void scriptapi_environment_step(lua_State *L, float dtime)
1416 assert(lua_checkstack(L, 20));
1417 //infostream<<"scriptapi_environment_step"<<std::endl;
1418 StackUnroller stack_unroller(L);
1420 // Get minetest.registered_globalsteps
1421 lua_getglobal(L, "minetest");
1422 lua_getfield(L, -1, "registered_globalsteps");
1423 luaL_checktype(L, -1, LUA_TTABLE);
1424 int table = lua_gettop(L);
1427 while(lua_next(L, table) != 0){
1428 // key at index -2 and value at index -1
1429 luaL_checktype(L, -1, LUA_TFUNCTION);
1431 lua_pushnumber(L, dtime);
1432 if(lua_pcall(L, 1, 0, 0))
1433 script_error(L, "error: %s\n", lua_tostring(L, -1));
1434 // value removed, keep key for next iteration
1438 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
1439 ServerActiveObject *placer)
1442 assert(lua_checkstack(L, 20));
1443 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
1444 StackUnroller stack_unroller(L);
1446 // Get server from registry
1447 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1448 Server *server = (Server*)lua_touserdata(L, -1);
1449 // And get the writable node definition manager from the server
1450 IWritableNodeDefManager *ndef =
1451 server->getWritableNodeDefManager();
1453 // Get minetest.registered_on_placenodes
1454 lua_getglobal(L, "minetest");
1455 lua_getfield(L, -1, "registered_on_placenodes");
1456 luaL_checktype(L, -1, LUA_TTABLE);
1457 int table = lua_gettop(L);
1460 while(lua_next(L, table) != 0){
1461 // key at index -2 and value at index -1
1462 luaL_checktype(L, -1, LUA_TFUNCTION);
1465 pushnode(L, newnode, ndef);
1466 objectref_get_or_create(L, placer);
1467 if(lua_pcall(L, 3, 0, 0))
1468 script_error(L, "error: %s\n", lua_tostring(L, -1));
1469 // value removed, keep key for next iteration
1473 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
1474 ServerActiveObject *digger)
1477 assert(lua_checkstack(L, 20));
1478 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
1479 StackUnroller stack_unroller(L);
1481 // Get server from registry
1482 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1483 Server *server = (Server*)lua_touserdata(L, -1);
1484 // And get the writable node definition manager from the server
1485 IWritableNodeDefManager *ndef =
1486 server->getWritableNodeDefManager();
1488 // Get minetest.registered_on_dignodes
1489 lua_getglobal(L, "minetest");
1490 lua_getfield(L, -1, "registered_on_dignodes");
1491 luaL_checktype(L, -1, LUA_TTABLE);
1492 int table = lua_gettop(L);
1495 while(lua_next(L, table) != 0){
1496 // key at index -2 and value at index -1
1497 luaL_checktype(L, -1, LUA_TFUNCTION);
1500 pushnode(L, oldnode, ndef);
1501 objectref_get_or_create(L, digger);
1502 if(lua_pcall(L, 3, 0, 0))
1503 script_error(L, "error: %s\n", lua_tostring(L, -1));
1504 // value removed, keep key for next iteration
1508 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
1509 ServerActiveObject *puncher)
1512 assert(lua_checkstack(L, 20));
1513 //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
1514 StackUnroller stack_unroller(L);
1516 // Get server from registry
1517 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1518 Server *server = (Server*)lua_touserdata(L, -1);
1519 // And get the writable node definition manager from the server
1520 IWritableNodeDefManager *ndef =
1521 server->getWritableNodeDefManager();
1523 // Get minetest.registered_on_punchnodes
1524 lua_getglobal(L, "minetest");
1525 lua_getfield(L, -1, "registered_on_punchnodes");
1526 luaL_checktype(L, -1, LUA_TTABLE);
1527 int table = lua_gettop(L);
1530 while(lua_next(L, table) != 0){
1531 // key at index -2 and value at index -1
1532 luaL_checktype(L, -1, LUA_TFUNCTION);
1535 pushnode(L, node, ndef);
1536 objectref_get_or_create(L, puncher);
1537 if(lua_pcall(L, 3, 0, 0))
1538 script_error(L, "error: %s\n", lua_tostring(L, -1));
1539 // value removed, keep key for next iteration
1547 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
1548 const std::string &staticdata)
1551 assert(lua_checkstack(L, 20));
1552 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
1553 <<name<<"\""<<std::endl;
1554 StackUnroller stack_unroller(L);
1556 // Get minetest.registered_entities[name]
1557 lua_getglobal(L, "minetest");
1558 lua_getfield(L, -1, "registered_entities");
1559 luaL_checktype(L, -1, LUA_TTABLE);
1560 lua_pushstring(L, name);
1561 lua_gettable(L, -2);
1562 // Should be a table, which we will use as a prototype
1563 //luaL_checktype(L, -1, LUA_TTABLE);
1564 if(lua_type(L, -1) != LUA_TTABLE){
1565 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
1568 int prototype_table = lua_gettop(L);
1569 //dump2(L, "prototype_table");
1571 // Create entity object
1573 int object = lua_gettop(L);
1575 // Set object metatable
1576 lua_pushvalue(L, prototype_table);
1577 lua_setmetatable(L, -2);
1579 // Add object reference
1580 // This should be userdata with metatable ObjectRef
1581 objectref_get(L, id);
1582 luaL_checktype(L, -1, LUA_TUSERDATA);
1583 if(!luaL_checkudata(L, -1, "ObjectRef"))
1584 luaL_typerror(L, -1, "ObjectRef");
1585 lua_setfield(L, -2, "object");
1587 // minetest.luaentities[id] = object
1588 lua_getglobal(L, "minetest");
1589 lua_getfield(L, -1, "luaentities");
1590 luaL_checktype(L, -1, LUA_TTABLE);
1591 lua_pushnumber(L, id); // Push id
1592 lua_pushvalue(L, object); // Copy object to top of stack
1593 lua_settable(L, -3);
1595 // Get on_activate function
1596 lua_pushvalue(L, object);
1597 lua_getfield(L, -1, "on_activate");
1598 if(!lua_isnil(L, -1)){
1599 luaL_checktype(L, -1, LUA_TFUNCTION);
1600 lua_pushvalue(L, object); // self
1601 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
1602 // Call with 2 arguments, 0 results
1603 if(lua_pcall(L, 2, 0, 0))
1604 script_error(L, "error running function %s:on_activate: %s\n",
1605 name, lua_tostring(L, -1));
1611 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1614 assert(lua_checkstack(L, 20));
1615 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
1617 // Get minetest.luaentities table
1618 lua_getglobal(L, "minetest");
1619 lua_getfield(L, -1, "luaentities");
1620 luaL_checktype(L, -1, LUA_TTABLE);
1621 int objectstable = lua_gettop(L);
1623 // Set luaentities[id] = nil
1624 lua_pushnumber(L, id); // Push id
1626 lua_settable(L, objectstable);
1628 lua_pop(L, 2); // pop luaentities, minetest
1631 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
1634 assert(lua_checkstack(L, 20));
1635 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
1636 StackUnroller stack_unroller(L);
1638 // Get minetest.luaentities[id]
1639 luaentity_get(L, id);
1640 int object = lua_gettop(L);
1642 // Get get_staticdata function
1643 lua_pushvalue(L, object);
1644 lua_getfield(L, -1, "get_staticdata");
1645 if(lua_isnil(L, -1))
1648 luaL_checktype(L, -1, LUA_TFUNCTION);
1649 lua_pushvalue(L, object); // self
1650 // Call with 1 arguments, 1 results
1651 if(lua_pcall(L, 1, 1, 0))
1652 script_error(L, "error running function get_staticdata: %s\n",
1653 lua_tostring(L, -1));
1656 const char *s = lua_tolstring(L, -1, &len);
1657 return std::string(s, len);
1660 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1661 LuaEntityProperties *prop)
1664 assert(lua_checkstack(L, 20));
1665 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1666 StackUnroller stack_unroller(L);
1668 // Get minetest.luaentities[id]
1669 luaentity_get(L, id);
1670 //int object = lua_gettop(L);
1672 lua_getfield(L, -1, "physical");
1673 if(lua_isboolean(L, -1))
1674 prop->physical = lua_toboolean(L, -1);
1677 lua_getfield(L, -1, "weight");
1678 prop->weight = lua_tonumber(L, -1);
1681 lua_getfield(L, -1, "collisionbox");
1682 if(lua_istable(L, -1)){
1683 lua_rawgeti(L, -1, 1);
1684 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
1686 lua_rawgeti(L, -1, 2);
1687 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
1689 lua_rawgeti(L, -1, 3);
1690 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
1692 lua_rawgeti(L, -1, 4);
1693 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
1695 lua_rawgeti(L, -1, 5);
1696 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
1698 lua_rawgeti(L, -1, 6);
1699 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
1704 lua_getfield(L, -1, "visual");
1705 if(lua_isstring(L, -1))
1706 prop->visual = lua_tostring(L, -1);
1709 lua_getfield(L, -1, "textures");
1710 if(lua_istable(L, -1)){
1711 prop->textures.clear();
1712 int table = lua_gettop(L);
1714 while(lua_next(L, table) != 0){
1715 // key at index -2 and value at index -1
1716 if(lua_isstring(L, -1))
1717 prop->textures.push_back(lua_tostring(L, -1));
1719 prop->textures.push_back("");
1720 // removes value, keeps key for next iteration
1728 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1731 assert(lua_checkstack(L, 20));
1732 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1733 StackUnroller stack_unroller(L);
1735 // Get minetest.luaentities[id]
1736 luaentity_get(L, id);
1737 int object = lua_gettop(L);
1738 // State: object is at top of stack
1739 // Get step function
1740 lua_getfield(L, -1, "on_step");
1741 if(lua_isnil(L, -1))
1743 luaL_checktype(L, -1, LUA_TFUNCTION);
1744 lua_pushvalue(L, object); // self
1745 lua_pushnumber(L, dtime); // dtime
1746 // Call with 2 arguments, 0 results
1747 if(lua_pcall(L, 2, 0, 0))
1748 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
1751 // Calls entity:on_punch(ObjectRef puncher)
1752 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1753 ServerActiveObject *puncher)
1756 assert(lua_checkstack(L, 20));
1757 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1758 StackUnroller stack_unroller(L);
1760 // Get minetest.luaentities[id]
1761 luaentity_get(L, id);
1762 int object = lua_gettop(L);
1763 // State: object is at top of stack
1765 lua_getfield(L, -1, "on_punch");
1766 if(lua_isnil(L, -1))
1768 luaL_checktype(L, -1, LUA_TFUNCTION);
1769 lua_pushvalue(L, object); // self
1770 objectref_get_or_create(L, puncher); // Clicker reference
1771 // Call with 2 arguments, 0 results
1772 if(lua_pcall(L, 2, 0, 0))
1773 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1776 // Calls entity:on_rightclick(ObjectRef clicker)
1777 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1778 ServerActiveObject *clicker)
1781 assert(lua_checkstack(L, 20));
1782 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1783 StackUnroller stack_unroller(L);
1785 // Get minetest.luaentities[id]
1786 luaentity_get(L, id);
1787 int object = lua_gettop(L);
1788 // State: object is at top of stack
1790 lua_getfield(L, -1, "on_rightclick");
1791 if(lua_isnil(L, -1))
1793 luaL_checktype(L, -1, LUA_TFUNCTION);
1794 lua_pushvalue(L, object); // self
1795 objectref_get_or_create(L, clicker); // Clicker reference
1796 // Call with 2 arguments, 0 results
1797 if(lua_pcall(L, 2, 0, 0))
1798 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));