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";
502 Read definiton from Lua
507 /* Visual definition */
509 f.drawtype = (NodeDrawType)getenumfield(L, table0, "drawtype", es_DrawType,
511 getfloatfield(L, table0, "visual_scale", f.visual_scale);
513 lua_getfield(L, table0, "tile_images");
514 if(lua_istable(L, -1)){
515 int table = lua_gettop(L);
518 while(lua_next(L, table) != 0){
519 // key at index -2 and value at index -1
520 if(lua_isstring(L, -1))
521 f.tname_tiles[i] = lua_tostring(L, -1);
523 f.tname_tiles[i] = "";
524 // removes value, keeps key for next iteration
532 // Copy last value to all remaining textures
534 std::string lastname = f.tname_tiles[i-1];
536 f.tname_tiles[i] = lastname;
543 getstringfield(L, table0, "inventory_image", f.tname_inventory);
545 lua_getfield(L, table0, "special_materials");
546 if(lua_istable(L, -1)){
547 int table = lua_gettop(L);
550 while(lua_next(L, table) != 0){
551 // key at index -2 and value at index -1
552 int smtable = lua_gettop(L);
553 std::string tname = getstringfield_default(
554 L, smtable, "image", "");
555 bool backface_culling = getboolfield_default(
556 L, smtable, "backface_culling", true);
557 MaterialSpec mspec(tname, backface_culling);
558 f.setSpecialMaterial(i, mspec);
559 // removes value, keeps key for next iteration
570 f.alpha = getintfield_default(L, table0, "alpha", 255);
574 lua_getfield(L, table0, "post_effect_color");
575 if(!lua_isnil(L, -1))
576 f.post_effect_color = readARGB8(L, -1);
579 f.param_type = (ContentParamType)getenumfield(L, table0, "paramtype",
580 es_ContentParamType, CPT_NONE);
582 // True for all ground-like things like stone and mud, false for eg. trees
583 getboolfield(L, table0, "is_ground_content", f.is_ground_content);
584 getboolfield(L, table0, "light_propagates", f.light_propagates);
585 getboolfield(L, table0, "sunlight_propagates", f.sunlight_propagates);
586 // This is used for collision detection.
587 // Also for general solidness queries.
588 getboolfield(L, table0, "walkable", f.walkable);
589 // Player can point to these
590 getboolfield(L, table0, "pointable", f.pointable);
591 // Player can dig these
592 getboolfield(L, table0, "diggable", f.diggable);
593 // Player can climb these
594 getboolfield(L, table0, "climbable", f.climbable);
595 // Player can build on these
596 getboolfield(L, table0, "buildable_to", f.buildable_to);
597 // If true, param2 is set to direction when placed. Used for torches.
598 // NOTE: the direction format is quite inefficient and should be changed
599 getboolfield(L, table0, "wall_mounted", f.wall_mounted);
600 // If true, node is equivalent to air. Torches are, air is. Water is not.
601 // Is used for example to check whether a mud block can have grass on.
602 getboolfield(L, table0, "air_equivalent", f.air_equivalent);
603 // Whether this content type often contains mineral.
604 // Used for texture atlas creation.
605 // Currently only enabled for CONTENT_STONE.
606 getboolfield(L, table0, "often_contains_mineral", f.often_contains_mineral);
607 // Inventory item string as which the node appears in inventory when dug.
608 // Mineral overrides this.
609 getstringfield(L, table0, "dug_item", f.dug_item);
610 // Extra dug item and its rarity
611 getstringfield(L, table0, "extra_dug_item", f.extra_dug_item);
612 // Usual get interval for extra dug item
613 getintfield(L, table0, "extra_dug_item_rarity", f.extra_dug_item_rarity);
614 // Metadata name of node (eg. "furnace")
615 getstringfield(L, table0, "metadata_name", f.metadata_name);
616 // Whether the node is non-liquid, source liquid or flowing liquid
617 f.liquid_type = (LiquidType)getenumfield(L, table0, "liquidtype",
618 es_LiquidType, LIQUID_NONE);
619 // If the content is liquid, this is the flowing version of the liquid.
620 getstringfield(L, table0, "liquid_alternative_flowing",
621 f.liquid_alternative_flowing);
622 // If the content is liquid, this is the source version of the liquid.
623 getstringfield(L, table0, "liquid_alternative_source",
624 f.liquid_alternative_source);
625 // Viscosity for fluid flow, ranging from 1 to 7, with
626 // 1 giving almost instantaneous propagation and 7 being
627 // the slowest possible
628 f.liquid_viscosity = getintfield_default(L, table0,
629 "liquid_viscosity", f.liquid_viscosity);
630 // Amount of light the node emits
631 f.light_source = getintfield_default(L, table0,
632 "light_source", f.light_source);
633 f.damage_per_second = getintfield_default(L, table0,
634 "damage_per_second", f.damage_per_second);
636 lua_getfield(L, table0, "selection_box");
637 if(lua_istable(L, -1)){
638 f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
639 es_NodeBoxType, NODEBOX_REGULAR);
641 lua_getfield(L, -1, "fixed");
642 if(lua_istable(L, -1))
643 f.selection_box.fixed = read_aabbox3df32(L, -1);
646 lua_getfield(L, -1, "wall_top");
647 if(lua_istable(L, -1))
648 f.selection_box.wall_top = read_aabbox3df32(L, -1);
651 lua_getfield(L, -1, "wall_bottom");
652 if(lua_istable(L, -1))
653 f.selection_box.wall_bottom = read_aabbox3df32(L, -1);
656 lua_getfield(L, -1, "wall_side");
657 if(lua_istable(L, -1))
658 f.selection_box.wall_side = read_aabbox3df32(L, -1);
663 lua_getfield(L, table0, "material");
664 if(lua_istable(L, -1)){
665 f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
666 es_Diggability, DIGGABLE_NORMAL);
668 getfloatfield(L, -1, "constant_time", f.material.constant_time);
669 getfloatfield(L, -1, "weight", f.material.weight);
670 getfloatfield(L, -1, "crackiness", f.material.crackiness);
671 getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
672 getfloatfield(L, -1, "cuttability", f.material.cuttability);
673 getfloatfield(L, -1, "flammability", f.material.flammability);
677 getstringfield(L, table0, "cookresult_item", f.cookresult_item);
678 getfloatfield(L, table0, "furnace_cooktime", f.furnace_cooktime);
679 getfloatfield(L, table0, "furnace_burntime", f.furnace_burntime);
685 nodedef->set(name, f);
687 return 0; /* number of results */
690 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
691 static int l_register_craft(lua_State *L)
693 infostream<<"register_craft"<<std::endl;
694 luaL_checktype(L, 1, LUA_TTABLE);
697 // Get server from registry
698 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
699 Server *server = (Server*)lua_touserdata(L, -1);
700 // And get the writable craft definition manager from the server
701 IWritableCraftDefManager *craftdef =
702 server->getWritableCraftDefManager();
706 std::vector<std::string> input;
708 lua_getfield(L, table0, "output");
709 luaL_checktype(L, -1, LUA_TSTRING);
710 if(lua_isstring(L, -1))
711 output = lua_tostring(L, -1);
714 lua_getfield(L, table0, "recipe");
715 luaL_checktype(L, -1, LUA_TTABLE);
716 if(lua_istable(L, -1)){
717 int table1 = lua_gettop(L);
720 while(lua_next(L, table1) != 0){
722 // key at index -2 and value at index -1
723 luaL_checktype(L, -1, LUA_TTABLE);
724 if(lua_istable(L, -1)){
725 int table2 = lua_gettop(L);
727 while(lua_next(L, table2) != 0){
728 // key at index -2 and value at index -1
729 luaL_checktype(L, -1, LUA_TSTRING);
730 input.push_back(lua_tostring(L, -1));
731 // removes value, keeps key for next iteration
739 if(colcount != width){
740 script_error(L, "error: %s\n", "Invalid crafting recipe");
743 // removes value, keeps key for next iteration
750 CraftDefinition def(output, width, input);
751 craftdef->registerCraft(def);
753 return 0; /* number of results */
756 static int register_lua_callback(lua_State *L, const char *tablename)
758 luaL_checktype(L, 1, LUA_TFUNCTION);
760 lua_getglobal(L, "table");
761 lua_getfield(L, -1, "insert");
762 int table_insert = lua_gettop(L);
763 // Get minetest.registered_globalsteps
764 lua_getglobal(L, "minetest");
765 lua_getfield(L, -1, tablename);
766 luaL_checktype(L, -1, LUA_TTABLE);
767 int registered = lua_gettop(L);
768 // table.insert(registered_globalsteps, func)
769 lua_pushvalue(L, table_insert);
770 lua_pushvalue(L, registered);
771 lua_pushvalue(L, 1); // push function from argument 1
773 if(lua_pcall(L, 2, 0, 0))
774 script_error(L, "error: %s\n", lua_tostring(L, -1));
776 return 0; /* number of results */
779 // Register a global step function
780 // register_globalstep(function)
781 static int l_register_globalstep(lua_State *L)
783 infostream<<"register_globalstep"<<std::endl;
784 return register_lua_callback(L, "registered_globalsteps");
787 // register_on_placenode(function)
788 static int l_register_on_placenode(lua_State *L)
790 infostream<<"register_on_placenode"<<std::endl;
791 return register_lua_callback(L, "registered_on_placenodes");
794 // register_on_dignode(function)
795 static int l_register_on_dignode(lua_State *L)
797 infostream<<"register_on_dignode"<<std::endl;
798 return register_lua_callback(L, "registered_on_dignodes");
801 // register_on_punchnode(function)
802 static int l_register_on_punchnode(lua_State *L)
804 infostream<<"register_on_punchnode"<<std::endl;
805 return register_lua_callback(L, "registered_on_punchnodes");
808 static const struct luaL_Reg minetest_f [] = {
809 {"register_entity", l_register_entity},
810 {"register_tool", l_register_tool},
811 {"register_node", l_register_node},
812 {"register_craft", l_register_craft},
813 {"register_globalstep", l_register_globalstep},
814 {"register_on_placenode", l_register_on_placenode},
815 {"register_on_dignode", l_register_on_dignode},
816 {"register_on_punchnode", l_register_on_punchnode},
824 static const struct luaL_Reg minetest_entity_m [] = {
829 Getters for stuff in main tables
832 static void objectref_get(lua_State *L, u16 id)
834 // Get minetest.object_refs[i]
835 lua_getglobal(L, "minetest");
836 lua_getfield(L, -1, "object_refs");
837 luaL_checktype(L, -1, LUA_TTABLE);
838 lua_pushnumber(L, id);
840 lua_remove(L, -2); // object_refs
841 lua_remove(L, -2); // minetest
844 static void luaentity_get(lua_State *L, u16 id)
846 // Get minetest.luaentities[i]
847 lua_getglobal(L, "minetest");
848 lua_getfield(L, -1, "luaentities");
849 luaL_checktype(L, -1, LUA_TTABLE);
850 lua_pushnumber(L, id);
852 lua_remove(L, -2); // luaentities
853 lua_remove(L, -2); // minetest
859 #define method(class, name) {#name, class::l_##name}
864 ServerEnvironment *m_env;
866 static const char className[];
867 static const luaL_reg methods[];
869 static EnvRef *checkobject(lua_State *L, int narg)
871 luaL_checktype(L, narg, LUA_TUSERDATA);
872 void *ud = luaL_checkudata(L, narg, className);
873 if(!ud) luaL_typerror(L, narg, className);
874 return *(EnvRef**)ud; // unbox pointer
877 // Exported functions
879 // EnvRef:add_node(pos, node)
880 // pos = {x=num, y=num, z=num}
881 static int l_add_node(lua_State *L)
883 infostream<<"EnvRef::l_add_node()"<<std::endl;
884 EnvRef *o = checkobject(L, 1);
885 ServerEnvironment *env = o->m_env;
886 if(env == NULL) return 0;
888 v3s16 pos = readpos(L, 2);
890 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
892 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
893 lua_pushboolean(L, succeeded);
897 // EnvRef:remove_node(pos)
898 // pos = {x=num, y=num, z=num}
899 static int l_remove_node(lua_State *L)
901 infostream<<"EnvRef::l_remove_node()"<<std::endl;
902 EnvRef *o = checkobject(L, 1);
903 ServerEnvironment *env = o->m_env;
904 if(env == NULL) return 0;
906 v3s16 pos = readpos(L, 2);
908 bool succeeded = env->getMap().removeNodeWithEvent(pos);
909 lua_pushboolean(L, succeeded);
913 // EnvRef:get_node(pos)
914 // pos = {x=num, y=num, z=num}
915 static int l_get_node(lua_State *L)
917 infostream<<"EnvRef::l_get_node()"<<std::endl;
918 EnvRef *o = checkobject(L, 1);
919 ServerEnvironment *env = o->m_env;
920 if(env == NULL) return 0;
922 v3s16 pos = readpos(L, 2);
924 MapNode n = env->getMap().getNodeNoEx(pos);
926 pushnode(L, n, env->getGameDef()->ndef());
930 // EnvRef:add_luaentity(pos, entityname)
931 // pos = {x=num, y=num, z=num}
932 static int l_add_luaentity(lua_State *L)
934 infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
935 EnvRef *o = checkobject(L, 1);
936 ServerEnvironment *env = o->m_env;
937 if(env == NULL) return 0;
939 v3f pos = readFloatPos(L, 2);
941 const char *name = lua_tostring(L, 3);
943 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
944 env->addActiveObject(obj);
948 static int gc_object(lua_State *L) {
949 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
955 EnvRef(ServerEnvironment *env):
958 infostream<<"EnvRef created"<<std::endl;
963 infostream<<"EnvRef destructing"<<std::endl;
966 // Creates an EnvRef and leaves it on top of stack
967 // Not callable from Lua; all references are created on the C side.
968 static void create(lua_State *L, ServerEnvironment *env)
970 EnvRef *o = new EnvRef(env);
971 //infostream<<"EnvRef::create: o="<<o<<std::endl;
972 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
973 luaL_getmetatable(L, className);
974 lua_setmetatable(L, -2);
977 static void set_null(lua_State *L)
979 EnvRef *o = checkobject(L, -1);
983 static void Register(lua_State *L)
986 int methodtable = lua_gettop(L);
987 luaL_newmetatable(L, className);
988 int metatable = lua_gettop(L);
990 lua_pushliteral(L, "__metatable");
991 lua_pushvalue(L, methodtable);
992 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
994 lua_pushliteral(L, "__index");
995 lua_pushvalue(L, methodtable);
996 lua_settable(L, metatable);
998 lua_pushliteral(L, "__gc");
999 lua_pushcfunction(L, gc_object);
1000 lua_settable(L, metatable);
1002 lua_pop(L, 1); // drop metatable
1004 luaL_openlib(L, 0, methods, 0); // fill methodtable
1005 lua_pop(L, 1); // drop methodtable
1007 // Cannot be created from Lua
1008 //lua_register(L, className, create_object);
1011 const char EnvRef::className[] = "EnvRef";
1012 const luaL_reg EnvRef::methods[] = {
1013 method(EnvRef, add_node),
1014 method(EnvRef, remove_node),
1015 method(EnvRef, get_node),
1016 method(EnvRef, add_luaentity),
1023 ServerActiveObject *m_object;
1025 static const char className[];
1026 static const luaL_reg methods[];
1028 static ObjectRef *checkobject(lua_State *L, int narg)
1030 luaL_checktype(L, narg, LUA_TUSERDATA);
1031 void *ud = luaL_checkudata(L, narg, className);
1032 if(!ud) luaL_typerror(L, narg, className);
1033 return *(ObjectRef**)ud; // unbox pointer
1036 static ServerActiveObject* getobject(ObjectRef *ref)
1038 ServerActiveObject *co = ref->m_object;
1042 static LuaEntitySAO* getluaobject(ObjectRef *ref)
1044 ServerActiveObject *obj = getobject(ref);
1047 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
1049 return (LuaEntitySAO*)obj;
1052 // Exported functions
1054 // garbage collector
1055 static int gc_object(lua_State *L) {
1056 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
1057 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
1063 static int l_remove(lua_State *L)
1065 ObjectRef *ref = checkobject(L, 1);
1066 ServerActiveObject *co = getobject(ref);
1067 if(co == NULL) return 0;
1068 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
1069 co->m_removed = true;
1074 // returns: {x=num, y=num, z=num}
1075 static int l_getpos(lua_State *L)
1077 ObjectRef *ref = checkobject(L, 1);
1078 ServerActiveObject *co = getobject(ref);
1079 if(co == NULL) return 0;
1080 v3f pos = co->getBasePosition() / BS;
1082 lua_pushnumber(L, pos.X);
1083 lua_setfield(L, -2, "x");
1084 lua_pushnumber(L, pos.Y);
1085 lua_setfield(L, -2, "y");
1086 lua_pushnumber(L, pos.Z);
1087 lua_setfield(L, -2, "z");
1091 // setpos(self, pos)
1092 static int l_setpos(lua_State *L)
1094 ObjectRef *ref = checkobject(L, 1);
1095 //LuaEntitySAO *co = getluaobject(ref);
1096 ServerActiveObject *co = getobject(ref);
1097 if(co == NULL) return 0;
1099 v3f pos = readFloatPos(L, 2);
1105 // moveto(self, pos, continuous=false)
1106 static int l_moveto(lua_State *L)
1108 ObjectRef *ref = checkobject(L, 1);
1109 //LuaEntitySAO *co = getluaobject(ref);
1110 ServerActiveObject *co = getobject(ref);
1111 if(co == NULL) return 0;
1113 v3f pos = readFloatPos(L, 2);
1115 bool continuous = lua_toboolean(L, 3);
1117 co->moveTo(pos, continuous);
1121 // setvelocity(self, velocity)
1122 static int l_setvelocity(lua_State *L)
1124 ObjectRef *ref = checkobject(L, 1);
1125 LuaEntitySAO *co = getluaobject(ref);
1126 if(co == NULL) return 0;
1128 v3f pos = readFloatPos(L, 2);
1130 co->setVelocity(pos);
1134 // setacceleration(self, acceleration)
1135 static int l_setacceleration(lua_State *L)
1137 ObjectRef *ref = checkobject(L, 1);
1138 LuaEntitySAO *co = getluaobject(ref);
1139 if(co == NULL) return 0;
1141 v3f pos = readFloatPos(L, 2);
1143 co->setAcceleration(pos);
1147 // add_to_inventory(self, itemstring)
1148 // returns: true if item was added, false otherwise
1149 static int l_add_to_inventory(lua_State *L)
1151 ObjectRef *ref = checkobject(L, 1);
1152 luaL_checkstring(L, 2);
1153 ServerActiveObject *co = getobject(ref);
1154 if(co == NULL) return 0;
1156 const char *itemstring = lua_tostring(L, 2);
1157 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1158 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1160 std::istringstream is(itemstring, std::ios::binary);
1161 ServerEnvironment *env = co->getEnv();
1163 IGameDef *gamedef = env->getGameDef();
1164 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1165 infostream<<"item="<<env<<std::endl;
1166 bool fits = co->addToInventory(item);
1168 lua_pushboolean(L, fits);
1173 ObjectRef(ServerActiveObject *object):
1176 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1182 infostream<<"ObjectRef destructing for id="
1183 <<m_object->getId()<<std::endl;
1185 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1188 // Creates an ObjectRef and leaves it on top of stack
1189 // Not callable from Lua; all references are created on the C side.
1190 static void create(lua_State *L, ServerActiveObject *object)
1192 ObjectRef *o = new ObjectRef(object);
1193 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1194 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1195 luaL_getmetatable(L, className);
1196 lua_setmetatable(L, -2);
1199 static void set_null(lua_State *L)
1201 ObjectRef *o = checkobject(L, -1);
1205 static void Register(lua_State *L)
1208 int methodtable = lua_gettop(L);
1209 luaL_newmetatable(L, className);
1210 int metatable = lua_gettop(L);
1212 lua_pushliteral(L, "__metatable");
1213 lua_pushvalue(L, methodtable);
1214 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1216 lua_pushliteral(L, "__index");
1217 lua_pushvalue(L, methodtable);
1218 lua_settable(L, metatable);
1220 lua_pushliteral(L, "__gc");
1221 lua_pushcfunction(L, gc_object);
1222 lua_settable(L, metatable);
1224 lua_pop(L, 1); // drop metatable
1226 luaL_openlib(L, 0, methods, 0); // fill methodtable
1227 lua_pop(L, 1); // drop methodtable
1229 // Cannot be created from Lua
1230 //lua_register(L, className, create_object);
1233 const char ObjectRef::className[] = "ObjectRef";
1234 const luaL_reg ObjectRef::methods[] = {
1235 method(ObjectRef, remove),
1236 method(ObjectRef, getpos),
1237 method(ObjectRef, setpos),
1238 method(ObjectRef, moveto),
1239 method(ObjectRef, setvelocity),
1240 method(ObjectRef, setacceleration),
1241 method(ObjectRef, add_to_inventory),
1245 // Creates a new anonymous reference if id=0
1246 static void objectref_get_or_create(lua_State *L,
1247 ServerActiveObject *cobj)
1249 if(cobj->getId() == 0){
1250 ObjectRef::create(L, cobj);
1252 objectref_get(L, cobj->getId());
1257 Main export function
1260 void scriptapi_export(lua_State *L, Server *server)
1263 assert(lua_checkstack(L, 20));
1264 infostream<<"scriptapi_export"<<std::endl;
1265 StackUnroller stack_unroller(L);
1267 // Store server as light userdata in registry
1268 lua_pushlightuserdata(L, server);
1269 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
1271 // Register global functions in table minetest
1273 luaL_register(L, NULL, minetest_f);
1274 lua_setglobal(L, "minetest");
1276 // Get the main minetest table
1277 lua_getglobal(L, "minetest");
1279 // Add tables to minetest
1282 lua_setfield(L, -2, "registered_blocks");*/
1285 lua_setfield(L, -2, "registered_entities");
1288 lua_setfield(L, -2, "registered_globalsteps");
1291 lua_setfield(L, -2, "registered_on_placenodes");
1294 lua_setfield(L, -2, "registered_on_dignodes");
1297 lua_setfield(L, -2, "registered_on_punchnodes");
1300 lua_setfield(L, -2, "object_refs");
1303 lua_setfield(L, -2, "luaentities");
1305 // Create entity prototype
1306 luaL_newmetatable(L, "minetest.entity");
1307 // metatable.__index = metatable
1308 lua_pushvalue(L, -1); // Duplicate metatable
1309 lua_setfield(L, -2, "__index");
1310 // Put functions in metatable
1311 luaL_register(L, NULL, minetest_entity_m);
1312 // Put other stuff in metatable
1314 // Environment C reference
1315 EnvRef::Register(L);
1317 // Object C reference
1318 ObjectRef::Register(L);
1321 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
1324 assert(lua_checkstack(L, 20));
1325 infostream<<"scriptapi_add_environment"<<std::endl;
1326 StackUnroller stack_unroller(L);
1328 // Create EnvRef on stack
1329 EnvRef::create(L, env);
1330 int envref = lua_gettop(L);
1332 // minetest.env = envref
1333 lua_getglobal(L, "minetest");
1334 luaL_checktype(L, -1, LUA_TTABLE);
1335 lua_pushvalue(L, envref);
1336 lua_setfield(L, -2, "env");
1340 // Dump stack top with the dump2 function
1341 static void dump2(lua_State *L, const char *name)
1343 // Dump object (debug)
1344 lua_getglobal(L, "dump2");
1345 luaL_checktype(L, -1, LUA_TFUNCTION);
1346 lua_pushvalue(L, -2); // Get previous stack top as first parameter
1347 lua_pushstring(L, name);
1348 if(lua_pcall(L, 2, 0, 0))
1349 script_error(L, "error: %s\n", lua_tostring(L, -1));
1357 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1360 assert(lua_checkstack(L, 20));
1361 infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1362 StackUnroller stack_unroller(L);
1364 // Create object on stack
1365 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1366 int object = lua_gettop(L);
1368 // Get minetest.object_refs table
1369 lua_getglobal(L, "minetest");
1370 lua_getfield(L, -1, "object_refs");
1371 luaL_checktype(L, -1, LUA_TTABLE);
1372 int objectstable = lua_gettop(L);
1374 // object_refs[id] = object
1375 lua_pushnumber(L, cobj->getId()); // Push id
1376 lua_pushvalue(L, object); // Copy object to top of stack
1377 lua_settable(L, objectstable);
1380 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1383 assert(lua_checkstack(L, 20));
1384 infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1385 StackUnroller stack_unroller(L);
1387 // Get minetest.object_refs table
1388 lua_getglobal(L, "minetest");
1389 lua_getfield(L, -1, "object_refs");
1390 luaL_checktype(L, -1, LUA_TTABLE);
1391 int objectstable = lua_gettop(L);
1393 // Get object_refs[id]
1394 lua_pushnumber(L, cobj->getId()); // Push id
1395 lua_gettable(L, objectstable);
1396 // Set object reference to NULL
1397 ObjectRef::set_null(L);
1398 lua_pop(L, 1); // pop object
1400 // Set object_refs[id] = nil
1401 lua_pushnumber(L, cobj->getId()); // Push id
1403 lua_settable(L, objectstable);
1410 void scriptapi_environment_step(lua_State *L, float dtime)
1413 assert(lua_checkstack(L, 20));
1414 //infostream<<"scriptapi_environment_step"<<std::endl;
1415 StackUnroller stack_unroller(L);
1417 // Get minetest.registered_globalsteps
1418 lua_getglobal(L, "minetest");
1419 lua_getfield(L, -1, "registered_globalsteps");
1420 luaL_checktype(L, -1, LUA_TTABLE);
1421 int table = lua_gettop(L);
1424 while(lua_next(L, table) != 0){
1425 // key at index -2 and value at index -1
1426 luaL_checktype(L, -1, LUA_TFUNCTION);
1428 lua_pushnumber(L, dtime);
1429 if(lua_pcall(L, 1, 0, 0))
1430 script_error(L, "error: %s\n", lua_tostring(L, -1));
1431 // value removed, keep key for next iteration
1435 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode)
1438 assert(lua_checkstack(L, 20));
1439 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
1440 StackUnroller stack_unroller(L);
1442 // Get server from registry
1443 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1444 Server *server = (Server*)lua_touserdata(L, -1);
1445 // And get the writable node definition manager from the server
1446 IWritableNodeDefManager *ndef =
1447 server->getWritableNodeDefManager();
1449 // Get minetest.registered_on_placenodes
1450 lua_getglobal(L, "minetest");
1451 lua_getfield(L, -1, "registered_on_placenodes");
1452 luaL_checktype(L, -1, LUA_TTABLE);
1453 int table = lua_gettop(L);
1456 while(lua_next(L, table) != 0){
1457 // key at index -2 and value at index -1
1458 luaL_checktype(L, -1, LUA_TFUNCTION);
1461 pushnode(L, newnode, ndef);
1462 if(lua_pcall(L, 2, 0, 0))
1463 script_error(L, "error: %s\n", lua_tostring(L, -1));
1464 // value removed, keep key for next iteration
1468 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode)
1471 assert(lua_checkstack(L, 20));
1472 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
1473 StackUnroller stack_unroller(L);
1475 // Get server from registry
1476 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1477 Server *server = (Server*)lua_touserdata(L, -1);
1478 // And get the writable node definition manager from the server
1479 IWritableNodeDefManager *ndef =
1480 server->getWritableNodeDefManager();
1482 // Get minetest.registered_on_dignodes
1483 lua_getglobal(L, "minetest");
1484 lua_getfield(L, -1, "registered_on_dignodes");
1485 luaL_checktype(L, -1, LUA_TTABLE);
1486 int table = lua_gettop(L);
1489 while(lua_next(L, table) != 0){
1490 // key at index -2 and value at index -1
1491 luaL_checktype(L, -1, LUA_TFUNCTION);
1494 pushnode(L, oldnode, ndef);
1495 if(lua_pcall(L, 2, 0, 0))
1496 script_error(L, "error: %s\n", lua_tostring(L, -1));
1497 // value removed, keep key for next iteration
1501 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode oldnode)
1504 assert(lua_checkstack(L, 20));
1505 //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
1506 StackUnroller stack_unroller(L);
1508 // Get server from registry
1509 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1510 Server *server = (Server*)lua_touserdata(L, -1);
1511 // And get the writable node definition manager from the server
1512 IWritableNodeDefManager *ndef =
1513 server->getWritableNodeDefManager();
1515 // Get minetest.registered_on_punchnodes
1516 lua_getglobal(L, "minetest");
1517 lua_getfield(L, -1, "registered_on_punchnodes");
1518 luaL_checktype(L, -1, LUA_TTABLE);
1519 int table = lua_gettop(L);
1522 while(lua_next(L, table) != 0){
1523 // key at index -2 and value at index -1
1524 luaL_checktype(L, -1, LUA_TFUNCTION);
1527 pushnode(L, oldnode, ndef);
1528 if(lua_pcall(L, 2, 0, 0))
1529 script_error(L, "error: %s\n", lua_tostring(L, -1));
1530 // value removed, keep key for next iteration
1538 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
1539 const std::string &staticdata)
1542 assert(lua_checkstack(L, 20));
1543 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
1544 <<name<<"\""<<std::endl;
1545 StackUnroller stack_unroller(L);
1547 // Get minetest.registered_entities[name]
1548 lua_getglobal(L, "minetest");
1549 lua_getfield(L, -1, "registered_entities");
1550 luaL_checktype(L, -1, LUA_TTABLE);
1551 lua_pushstring(L, name);
1552 lua_gettable(L, -2);
1553 // Should be a table, which we will use as a prototype
1554 //luaL_checktype(L, -1, LUA_TTABLE);
1555 if(lua_type(L, -1) != LUA_TTABLE){
1556 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
1559 int prototype_table = lua_gettop(L);
1560 //dump2(L, "prototype_table");
1562 // Create entity object
1564 int object = lua_gettop(L);
1566 // Set object metatable
1567 lua_pushvalue(L, prototype_table);
1568 lua_setmetatable(L, -2);
1570 // Add object reference
1571 // This should be userdata with metatable ObjectRef
1572 objectref_get(L, id);
1573 luaL_checktype(L, -1, LUA_TUSERDATA);
1574 if(!luaL_checkudata(L, -1, "ObjectRef"))
1575 luaL_typerror(L, -1, "ObjectRef");
1576 lua_setfield(L, -2, "object");
1578 // minetest.luaentities[id] = object
1579 lua_getglobal(L, "minetest");
1580 lua_getfield(L, -1, "luaentities");
1581 luaL_checktype(L, -1, LUA_TTABLE);
1582 lua_pushnumber(L, id); // Push id
1583 lua_pushvalue(L, object); // Copy object to top of stack
1584 lua_settable(L, -3);
1586 // Get on_activate function
1587 lua_pushvalue(L, object);
1588 lua_getfield(L, -1, "on_activate");
1589 if(!lua_isnil(L, -1)){
1590 luaL_checktype(L, -1, LUA_TFUNCTION);
1591 lua_pushvalue(L, object); // self
1592 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
1593 // Call with 2 arguments, 0 results
1594 if(lua_pcall(L, 2, 0, 0))
1595 script_error(L, "error running function %s:on_activate: %s\n",
1596 name, lua_tostring(L, -1));
1602 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1605 assert(lua_checkstack(L, 20));
1606 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
1608 // Get minetest.luaentities table
1609 lua_getglobal(L, "minetest");
1610 lua_getfield(L, -1, "luaentities");
1611 luaL_checktype(L, -1, LUA_TTABLE);
1612 int objectstable = lua_gettop(L);
1614 // Set luaentities[id] = nil
1615 lua_pushnumber(L, id); // Push id
1617 lua_settable(L, objectstable);
1619 lua_pop(L, 2); // pop luaentities, minetest
1622 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
1625 assert(lua_checkstack(L, 20));
1626 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
1627 StackUnroller stack_unroller(L);
1629 // Get minetest.luaentities[id]
1630 luaentity_get(L, id);
1631 int object = lua_gettop(L);
1633 // Get get_staticdata function
1634 lua_pushvalue(L, object);
1635 lua_getfield(L, -1, "get_staticdata");
1636 if(lua_isnil(L, -1))
1639 luaL_checktype(L, -1, LUA_TFUNCTION);
1640 lua_pushvalue(L, object); // self
1641 // Call with 1 arguments, 1 results
1642 if(lua_pcall(L, 1, 1, 0))
1643 script_error(L, "error running function get_staticdata: %s\n",
1644 lua_tostring(L, -1));
1647 const char *s = lua_tolstring(L, -1, &len);
1648 return std::string(s, len);
1651 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1652 LuaEntityProperties *prop)
1655 assert(lua_checkstack(L, 20));
1656 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1657 StackUnroller stack_unroller(L);
1659 // Get minetest.luaentities[id]
1660 luaentity_get(L, id);
1661 //int object = lua_gettop(L);
1663 lua_getfield(L, -1, "physical");
1664 if(lua_isboolean(L, -1))
1665 prop->physical = lua_toboolean(L, -1);
1668 lua_getfield(L, -1, "weight");
1669 prop->weight = lua_tonumber(L, -1);
1672 lua_getfield(L, -1, "collisionbox");
1673 if(lua_istable(L, -1)){
1674 lua_rawgeti(L, -1, 1);
1675 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
1677 lua_rawgeti(L, -1, 2);
1678 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
1680 lua_rawgeti(L, -1, 3);
1681 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
1683 lua_rawgeti(L, -1, 4);
1684 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
1686 lua_rawgeti(L, -1, 5);
1687 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
1689 lua_rawgeti(L, -1, 6);
1690 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
1695 lua_getfield(L, -1, "visual");
1696 if(lua_isstring(L, -1))
1697 prop->visual = lua_tostring(L, -1);
1700 lua_getfield(L, -1, "textures");
1701 if(lua_istable(L, -1)){
1702 prop->textures.clear();
1703 int table = lua_gettop(L);
1705 while(lua_next(L, table) != 0){
1706 // key at index -2 and value at index -1
1707 if(lua_isstring(L, -1))
1708 prop->textures.push_back(lua_tostring(L, -1));
1710 prop->textures.push_back("");
1711 // removes value, keeps key for next iteration
1719 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1722 assert(lua_checkstack(L, 20));
1723 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1724 StackUnroller stack_unroller(L);
1726 // Get minetest.luaentities[id]
1727 luaentity_get(L, id);
1728 int object = lua_gettop(L);
1729 // State: object is at top of stack
1730 // Get step function
1731 lua_getfield(L, -1, "on_step");
1732 if(lua_isnil(L, -1))
1734 luaL_checktype(L, -1, LUA_TFUNCTION);
1735 lua_pushvalue(L, object); // self
1736 lua_pushnumber(L, dtime); // dtime
1737 // Call with 2 arguments, 0 results
1738 if(lua_pcall(L, 2, 0, 0))
1739 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
1742 // Calls entity:on_punch(ObjectRef puncher)
1743 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1744 ServerActiveObject *puncher)
1747 assert(lua_checkstack(L, 20));
1748 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1749 StackUnroller stack_unroller(L);
1751 // Get minetest.luaentities[id]
1752 luaentity_get(L, id);
1753 int object = lua_gettop(L);
1754 // State: object is at top of stack
1756 lua_getfield(L, -1, "on_punch");
1757 if(lua_isnil(L, -1))
1759 luaL_checktype(L, -1, LUA_TFUNCTION);
1760 lua_pushvalue(L, object); // self
1761 objectref_get_or_create(L, puncher); // Clicker reference
1762 // Call with 2 arguments, 0 results
1763 if(lua_pcall(L, 2, 0, 0))
1764 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1767 // Calls entity:on_rightclick(ObjectRef clicker)
1768 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1769 ServerActiveObject *clicker)
1772 assert(lua_checkstack(L, 20));
1773 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1774 StackUnroller stack_unroller(L);
1776 // Get minetest.luaentities[id]
1777 luaentity_get(L, id);
1778 int object = lua_gettop(L);
1779 // State: object is at top of stack
1781 lua_getfield(L, -1, "on_rightclick");
1782 if(lua_isnil(L, -1))
1784 luaL_checktype(L, -1, LUA_TFUNCTION);
1785 lua_pushvalue(L, object); // self
1786 objectref_get_or_create(L, clicker); // Clicker reference
1787 // Call with 2 arguments, 0 results
1788 if(lua_pcall(L, 2, 0, 0))
1789 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));