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_type =
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 bool getstringfield(lua_State *L, int table,
216 const char *fieldname, std::string &result)
218 lua_getfield(L, table, fieldname);
220 if(lua_isstring(L, -1)){
221 result = lua_tostring(L, -1);
228 static bool getintfield(lua_State *L, int table,
229 const char *fieldname, int &result)
231 lua_getfield(L, table, fieldname);
233 if(lua_isnumber(L, -1)){
234 result = lua_tonumber(L, -1);
241 static bool getfloatfield(lua_State *L, int table,
242 const char *fieldname, float &result)
244 lua_getfield(L, table, fieldname);
246 if(lua_isnumber(L, -1)){
247 result = lua_tonumber(L, -1);
254 static bool getboolfield(lua_State *L, int table,
255 const char *fieldname, bool &result)
257 lua_getfield(L, table, fieldname);
259 if(lua_isboolean(L, -1)){
260 result = lua_toboolean(L, -1);
267 static std::string getstringfield_default(lua_State *L, int table,
268 const char *fieldname, const std::string &default_)
270 std::string result = default_;
271 getstringfield(L, table, fieldname, result);
275 static int getintfield_default(lua_State *L, int table,
276 const char *fieldname, int default_)
278 int result = default_;
279 getintfield(L, table, fieldname, result);
283 static bool getboolfield_default(lua_State *L, int table,
284 const char *fieldname, bool default_)
286 bool result = default_;
287 getboolfield(L, table, fieldname, result);
297 static bool string_to_enum(const EnumString *spec, int &result,
298 const std::string &str)
300 const EnumString *esp = spec;
302 if(str == std::string(esp->str)){
311 /*static bool enum_to_string(const EnumString *spec, std::string &result,
314 const EnumString *esp = spec;
325 static int getenumfield(lua_State *L, int table,
326 const char *fieldname, const EnumString *spec, int default_)
328 int result = default_;
329 string_to_enum(spec, result,
330 getstringfield_default(L, table, fieldname, ""));
334 struct EnumString es_DrawType[] =
336 {NDT_NORMAL, "normal"},
337 {NDT_AIRLIKE, "airlike"},
338 {NDT_LIQUID, "liquid"},
339 {NDT_FLOWINGLIQUID, "flowingliquid"},
340 {NDT_GLASSLIKE, "glasslike"},
341 {NDT_ALLFACES, "allfaces"},
342 {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
343 {NDT_TORCHLIKE, "torchlike"},
344 {NDT_SIGNLIKE, "signlike"},
345 {NDT_PLANTLIKE, "plantlike"},
346 {NDT_FENCELIKE, "fencelike"},
347 {NDT_RAILLIKE, "raillike"},
351 struct EnumString es_ContentParamType[] =
354 {CPT_LIGHT, "light"},
355 {CPT_MINERAL, "mineral"},
356 {CPT_FACEDIR_SIMPLE, "facedir_simple"},
363 // Register new object prototype
364 // register_entity(name, prototype)
365 static int l_register_entity(lua_State *L)
367 const char *name = luaL_checkstring(L, 1);
368 infostream<<"register_entity: "<<name<<std::endl;
369 luaL_checktype(L, 2, LUA_TTABLE);
371 // Get minetest.registered_entities
372 lua_getglobal(L, "minetest");
373 lua_getfield(L, -1, "registered_entities");
374 luaL_checktype(L, -1, LUA_TTABLE);
375 int registered_entities = lua_gettop(L);
376 lua_pushvalue(L, 2); // Object = param 2 -> stack top
377 // registered_entities[name] = object
378 lua_setfield(L, registered_entities, name);
380 // Get registered object to top of stack
383 // Set __index to point to itself
384 lua_pushvalue(L, -1);
385 lua_setfield(L, -2, "__index");
387 // Set metatable.__index = metatable
388 luaL_getmetatable(L, "minetest.entity");
389 lua_pushvalue(L, -1); // duplicate metatable
390 lua_setfield(L, -2, "__index");
391 // Set object metatable
392 lua_setmetatable(L, -2);
394 return 0; /* number of results */
397 // register_tool(name, {lots of stuff})
398 static int l_register_tool(lua_State *L)
400 const char *name = luaL_checkstring(L, 1);
401 infostream<<"register_tool: "<<name<<std::endl;
402 luaL_checktype(L, 2, LUA_TTABLE);
405 // Get server from registry
406 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
407 Server *server = (Server*)lua_touserdata(L, -1);
408 // And get the writable tool definition manager from the server
409 IWritableToolDefManager *tooldef =
410 server->getWritableToolDefManager();
414 getstringfield(L, table, "image", def.imagename);
415 getfloatfield(L, table, "basetime", def.properties.basetime);
416 getfloatfield(L, table, "dt_weight", def.properties.dt_weight);
417 getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness);
418 getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness);
419 getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability);
420 getfloatfield(L, table, "basedurability", def.properties.basedurability);
421 getfloatfield(L, table, "dd_weight", def.properties.dd_weight);
422 getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness);
423 getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness);
424 getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability);
426 tooldef->registerTool(name, def);
427 return 0; /* number of results */
430 // register_node(name, {lots of stuff})
431 static int l_register_node(lua_State *L)
433 const char *name = luaL_checkstring(L, 1);
434 infostream<<"register_node: "<<name<<std::endl;
435 luaL_checktype(L, 2, LUA_TTABLE);
438 // Get server from registry
439 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
440 Server *server = (Server*)lua_touserdata(L, -1);
441 // And get the writable node definition manager from the server
442 IWritableNodeDefManager *nodedef =
443 server->getWritableNodeDefManager();
453 f.drawtype = (NodeDrawType)getenumfield(L, table0, "drawtype", es_DrawType,
455 getfloatfield(L, table0, "visual_scale", f.visual_scale);
457 lua_getfield(L, table0, "tile_images");
458 if(lua_istable(L, -1)){
459 int table = lua_gettop(L);
462 while(lua_next(L, table) != 0){
463 // key at index -2 and value at index -1
464 if(lua_isstring(L, -1))
465 f.tname_tiles[i] = lua_tostring(L, -1);
467 f.tname_tiles[i] = "";
468 // removes value, keeps key for next iteration
479 getstringfield(L, table0, "inventory_image", f.tname_inventory);
481 lua_getfield(L, table0, "special_materials");
482 if(lua_istable(L, -1)){
483 int table = lua_gettop(L);
486 while(lua_next(L, table) != 0){
487 // key at index -2 and value at index -1
488 int smtable = lua_gettop(L);
489 std::string tname = getstringfield_default(
490 L, smtable, "image", "");
491 bool backface_culling = getboolfield_default(
492 L, smtable, "backface_culling", true);
493 MaterialSpec mspec(tname, backface_culling);
494 f.setSpecialMaterial(i, mspec);
495 // removes value, keeps key for next iteration
506 f.alpha = getintfield_default(L, table0, "alpha", 255);
512 lua_getfield(L, table0, "post_effect_color");
513 if(!lua_isnil(L, -1))
514 f.post_effect_color = readARGB8(L, -1);
516 f.param_type = (ContentParamType)getenumfield(L, table0, "paramtype",
517 es_ContentParamType, f.param_type);
519 // True for all ground-like things like stone and mud, false for eg. trees
520 getboolfield(L, table0, "is_ground_content", f.is_ground_content);
521 getboolfield(L, table0, "light_propagates", f.light_propagates);
522 getboolfield(L, table0, "sunlight_propagates", f.sunlight_propagates);
523 // This is used for collision detection.
524 // Also for general solidness queries.
525 getboolfield(L, table0, "walkable", f.walkable);
526 // Player can point to these
527 getboolfield(L, table0, "pointable", f.pointable);
528 // Player can dig these
529 getboolfield(L, table0, "diggable", f.diggable);
530 // Player can climb these
531 getboolfield(L, table0, "climbable", f.climbable);
532 // Player can build on these
533 getboolfield(L, table0, "buildable_to", f.buildable_to);
534 // If true, param2 is set to direction when placed. Used for torches.
535 // NOTE: the direction format is quite inefficient and should be changed
536 getboolfield(L, table0, "wall_mounted", f.wall_mounted);
537 // If true, node is equivalent to air. Torches are, air is. Water is not.
538 // Is used for example to check whether a mud block can have grass on.
539 getboolfield(L, table0, "air_equivalent", f.air_equivalent);
540 // Whether this content type often contains mineral.
541 // Used for texture atlas creation.
542 // Currently only enabled for CONTENT_STONE.
543 getboolfield(L, table0, "often_contains_mineral", f.often_contains_mineral);
544 // Inventory item string as which the node appears in inventory when dug.
545 // Mineral overrides this.
546 getstringfield(L, table0, "dug_item", f.dug_item);
547 // Extra dug item and its rarity
548 getstringfield(L, table0, "extra_dug_item", f.extra_dug_item);
549 // Usual get interval for extra dug item
550 getintfield(L, table0, "extra_dug_item_rarity", f.extra_dug_item_rarity);
551 // Metadata name of node (eg. "furnace")
552 getstringfield(L, table0, "metadata_name", f.metadata_name);
553 // Whether the node is non-liquid, source liquid or flowing liquid
555 // enum LiquidType liquid_type;
556 // If the content is liquid, this is the flowing version of the liquid.
558 // content_t liquid_alternative_flowing;
559 // If the content is liquid, this is the source version of the liquid.
561 // content_t liquid_alternative_source;
562 // Viscosity for fluid flow, ranging from 1 to 7, with
563 // 1 giving almost instantaneous propagation and 7 being
564 // the slowest possible
565 f.liquid_viscosity = getintfield_default(L, table0,
566 "liquid_viscosity", f.liquid_viscosity);
567 // Amount of light the node emits
568 f.light_source = getintfield_default(L, table0,
569 "light_source", f.light_source);
570 f.damage_per_second = getintfield_default(L, table0,
571 "damage_per_second", f.damage_per_second);
573 //NodeBox selection_box;
575 //MaterialProperties material;
576 getstringfield(L, table0, "cookresult_item", f.cookresult_item);
577 getfloatfield(L, table0, "furnace_cooktime", f.furnace_cooktime);
578 getfloatfield(L, table0, "furnace_burntime", f.furnace_burntime);
584 // TODO: Replace with actual parameter reading
585 // Temporarily set some sane parameters to allow digging
586 f.material.diggability = DIGGABLE_NORMAL;
587 f.material.weight = 0;
588 f.material.crackiness = 0;
589 f.material.crumbliness = 0;
590 f.material.cuttability = 0;
591 f.dug_item = std::string("NodeItem \"")+name+"\" 1";
596 nodedef->set(name, f);
598 return 0; /* number of results */
601 // register_craft({output=item, recipe={{item00,item10},{item01,item11}})
602 static int l_register_craft(lua_State *L)
604 infostream<<"register_craft"<<std::endl;
605 luaL_checktype(L, 1, LUA_TTABLE);
608 // Get server from registry
609 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
610 Server *server = (Server*)lua_touserdata(L, -1);
611 // And get the writable craft definition manager from the server
612 IWritableCraftDefManager *craftdef =
613 server->getWritableCraftDefManager();
617 std::vector<std::string> input;
619 lua_getfield(L, table0, "output");
620 luaL_checktype(L, -1, LUA_TSTRING);
621 if(lua_isstring(L, -1))
622 output = lua_tostring(L, -1);
625 lua_getfield(L, table0, "recipe");
626 luaL_checktype(L, -1, LUA_TTABLE);
627 if(lua_istable(L, -1)){
628 int table1 = lua_gettop(L);
631 while(lua_next(L, table1) != 0){
633 // key at index -2 and value at index -1
634 luaL_checktype(L, -1, LUA_TTABLE);
635 if(lua_istable(L, -1)){
636 int table2 = lua_gettop(L);
638 while(lua_next(L, table2) != 0){
639 // key at index -2 and value at index -1
640 luaL_checktype(L, -1, LUA_TSTRING);
641 input.push_back(lua_tostring(L, -1));
642 // removes value, keeps key for next iteration
650 if(colcount != width){
651 script_error(L, "error: %s\n", "Invalid crafting recipe");
654 // removes value, keeps key for next iteration
661 CraftDefinition def(output, width, input);
662 craftdef->registerCraft(def);
664 return 0; /* number of results */
667 static int register_lua_callback(lua_State *L, const char *tablename)
669 luaL_checktype(L, 1, LUA_TFUNCTION);
671 lua_getglobal(L, "table");
672 lua_getfield(L, -1, "insert");
673 int table_insert = lua_gettop(L);
674 // Get minetest.registered_globalsteps
675 lua_getglobal(L, "minetest");
676 lua_getfield(L, -1, tablename);
677 luaL_checktype(L, -1, LUA_TTABLE);
678 int registered = lua_gettop(L);
679 // table.insert(registered_globalsteps, func)
680 lua_pushvalue(L, table_insert);
681 lua_pushvalue(L, registered);
682 lua_pushvalue(L, 1); // push function from argument 1
684 if(lua_pcall(L, 2, 0, 0))
685 script_error(L, "error: %s\n", lua_tostring(L, -1));
687 return 0; /* number of results */
690 // Register a global step function
691 // register_globalstep(function)
692 static int l_register_globalstep(lua_State *L)
694 infostream<<"register_globalstep"<<std::endl;
695 return register_lua_callback(L, "registered_globalsteps");
698 // register_on_placenode(function)
699 static int l_register_on_placenode(lua_State *L)
701 infostream<<"register_on_placenode"<<std::endl;
702 return register_lua_callback(L, "registered_on_placenodes");
705 // register_on_dignode(function)
706 static int l_register_on_dignode(lua_State *L)
708 infostream<<"register_on_dignode"<<std::endl;
709 return register_lua_callback(L, "registered_on_dignodes");
712 // register_on_punchnode(function)
713 static int l_register_on_punchnode(lua_State *L)
715 infostream<<"register_on_punchnode"<<std::endl;
716 return register_lua_callback(L, "registered_on_punchnodes");
719 static const struct luaL_Reg minetest_f [] = {
720 {"register_entity", l_register_entity},
721 {"register_tool", l_register_tool},
722 {"register_node", l_register_node},
723 {"register_craft", l_register_craft},
724 {"register_globalstep", l_register_globalstep},
725 {"register_on_placenode", l_register_on_placenode},
726 {"register_on_dignode", l_register_on_dignode},
727 {"register_on_punchnode", l_register_on_punchnode},
735 static const struct luaL_Reg minetest_entity_m [] = {
740 Getters for stuff in main tables
743 static void objectref_get(lua_State *L, u16 id)
745 // Get minetest.object_refs[i]
746 lua_getglobal(L, "minetest");
747 lua_getfield(L, -1, "object_refs");
748 luaL_checktype(L, -1, LUA_TTABLE);
749 lua_pushnumber(L, id);
751 lua_remove(L, -2); // object_refs
752 lua_remove(L, -2); // minetest
755 static void luaentity_get(lua_State *L, u16 id)
757 // Get minetest.luaentities[i]
758 lua_getglobal(L, "minetest");
759 lua_getfield(L, -1, "luaentities");
760 luaL_checktype(L, -1, LUA_TTABLE);
761 lua_pushnumber(L, id);
763 lua_remove(L, -2); // luaentities
764 lua_remove(L, -2); // minetest
770 #define method(class, name) {#name, class::l_##name}
775 ServerEnvironment *m_env;
777 static const char className[];
778 static const luaL_reg methods[];
780 static EnvRef *checkobject(lua_State *L, int narg)
782 luaL_checktype(L, narg, LUA_TUSERDATA);
783 void *ud = luaL_checkudata(L, narg, className);
784 if(!ud) luaL_typerror(L, narg, className);
785 return *(EnvRef**)ud; // unbox pointer
788 // Exported functions
790 // EnvRef:add_node(pos, node)
791 // pos = {x=num, y=num, z=num}
792 static int l_add_node(lua_State *L)
794 infostream<<"EnvRef::l_add_node()"<<std::endl;
795 EnvRef *o = checkobject(L, 1);
796 ServerEnvironment *env = o->m_env;
797 if(env == NULL) return 0;
799 v3s16 pos = readpos(L, 2);
801 MapNode n = readnode(L, 3, env->getGameDef()->ndef());
803 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
804 lua_pushboolean(L, succeeded);
808 // EnvRef:remove_node(pos)
809 // pos = {x=num, y=num, z=num}
810 static int l_remove_node(lua_State *L)
812 infostream<<"EnvRef::l_remove_node()"<<std::endl;
813 EnvRef *o = checkobject(L, 1);
814 ServerEnvironment *env = o->m_env;
815 if(env == NULL) return 0;
817 v3s16 pos = readpos(L, 2);
819 bool succeeded = env->getMap().removeNodeWithEvent(pos);
820 lua_pushboolean(L, succeeded);
824 // EnvRef:get_node(pos)
825 // pos = {x=num, y=num, z=num}
826 static int l_get_node(lua_State *L)
828 infostream<<"EnvRef::l_get_node()"<<std::endl;
829 EnvRef *o = checkobject(L, 1);
830 ServerEnvironment *env = o->m_env;
831 if(env == NULL) return 0;
833 v3s16 pos = readpos(L, 2);
835 MapNode n = env->getMap().getNodeNoEx(pos);
837 pushnode(L, n, env->getGameDef()->ndef());
841 // EnvRef:add_luaentity(pos, entityname)
842 // pos = {x=num, y=num, z=num}
843 static int l_add_luaentity(lua_State *L)
845 infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
846 EnvRef *o = checkobject(L, 1);
847 ServerEnvironment *env = o->m_env;
848 if(env == NULL) return 0;
850 v3f pos = readFloatPos(L, 2);
852 const char *name = lua_tostring(L, 3);
854 ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
855 env->addActiveObject(obj);
859 static int gc_object(lua_State *L) {
860 EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1));
866 EnvRef(ServerEnvironment *env):
869 infostream<<"EnvRef created"<<std::endl;
874 infostream<<"EnvRef destructing"<<std::endl;
877 // Creates an EnvRef and leaves it on top of stack
878 // Not callable from Lua; all references are created on the C side.
879 static void create(lua_State *L, ServerEnvironment *env)
881 EnvRef *o = new EnvRef(env);
882 //infostream<<"EnvRef::create: o="<<o<<std::endl;
883 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
884 luaL_getmetatable(L, className);
885 lua_setmetatable(L, -2);
888 static void set_null(lua_State *L)
890 EnvRef *o = checkobject(L, -1);
894 static void Register(lua_State *L)
897 int methodtable = lua_gettop(L);
898 luaL_newmetatable(L, className);
899 int metatable = lua_gettop(L);
901 lua_pushliteral(L, "__metatable");
902 lua_pushvalue(L, methodtable);
903 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
905 lua_pushliteral(L, "__index");
906 lua_pushvalue(L, methodtable);
907 lua_settable(L, metatable);
909 lua_pushliteral(L, "__gc");
910 lua_pushcfunction(L, gc_object);
911 lua_settable(L, metatable);
913 lua_pop(L, 1); // drop metatable
915 luaL_openlib(L, 0, methods, 0); // fill methodtable
916 lua_pop(L, 1); // drop methodtable
918 // Cannot be created from Lua
919 //lua_register(L, className, create_object);
922 const char EnvRef::className[] = "EnvRef";
923 const luaL_reg EnvRef::methods[] = {
924 method(EnvRef, add_node),
925 method(EnvRef, remove_node),
926 method(EnvRef, get_node),
927 method(EnvRef, add_luaentity),
934 ServerActiveObject *m_object;
936 static const char className[];
937 static const luaL_reg methods[];
939 static ObjectRef *checkobject(lua_State *L, int narg)
941 luaL_checktype(L, narg, LUA_TUSERDATA);
942 void *ud = luaL_checkudata(L, narg, className);
943 if(!ud) luaL_typerror(L, narg, className);
944 return *(ObjectRef**)ud; // unbox pointer
947 static ServerActiveObject* getobject(ObjectRef *ref)
949 ServerActiveObject *co = ref->m_object;
953 static LuaEntitySAO* getluaobject(ObjectRef *ref)
955 ServerActiveObject *obj = getobject(ref);
958 if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
960 return (LuaEntitySAO*)obj;
963 // Exported functions
966 static int gc_object(lua_State *L) {
967 ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
968 //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
974 static int l_remove(lua_State *L)
976 ObjectRef *ref = checkobject(L, 1);
977 ServerActiveObject *co = getobject(ref);
978 if(co == NULL) return 0;
979 infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
980 co->m_removed = true;
985 // returns: {x=num, y=num, z=num}
986 static int l_getpos(lua_State *L)
988 ObjectRef *ref = checkobject(L, 1);
989 ServerActiveObject *co = getobject(ref);
990 if(co == NULL) return 0;
991 v3f pos = co->getBasePosition() / BS;
993 lua_pushnumber(L, pos.X);
994 lua_setfield(L, -2, "x");
995 lua_pushnumber(L, pos.Y);
996 lua_setfield(L, -2, "y");
997 lua_pushnumber(L, pos.Z);
998 lua_setfield(L, -2, "z");
1002 // setpos(self, pos)
1003 static int l_setpos(lua_State *L)
1005 ObjectRef *ref = checkobject(L, 1);
1006 //LuaEntitySAO *co = getluaobject(ref);
1007 ServerActiveObject *co = getobject(ref);
1008 if(co == NULL) return 0;
1010 v3f pos = readFloatPos(L, 2);
1016 // moveto(self, pos, continuous=false)
1017 static int l_moveto(lua_State *L)
1019 ObjectRef *ref = checkobject(L, 1);
1020 //LuaEntitySAO *co = getluaobject(ref);
1021 ServerActiveObject *co = getobject(ref);
1022 if(co == NULL) return 0;
1024 v3f pos = readFloatPos(L, 2);
1026 bool continuous = lua_toboolean(L, 3);
1028 co->moveTo(pos, continuous);
1032 // setvelocity(self, velocity)
1033 static int l_setvelocity(lua_State *L)
1035 ObjectRef *ref = checkobject(L, 1);
1036 LuaEntitySAO *co = getluaobject(ref);
1037 if(co == NULL) return 0;
1039 v3f pos = readFloatPos(L, 2);
1041 co->setVelocity(pos);
1045 // setacceleration(self, acceleration)
1046 static int l_setacceleration(lua_State *L)
1048 ObjectRef *ref = checkobject(L, 1);
1049 LuaEntitySAO *co = getluaobject(ref);
1050 if(co == NULL) return 0;
1052 v3f pos = readFloatPos(L, 2);
1054 co->setAcceleration(pos);
1058 // add_to_inventory(self, itemstring)
1059 // returns: true if item was added, false otherwise
1060 static int l_add_to_inventory(lua_State *L)
1062 ObjectRef *ref = checkobject(L, 1);
1063 luaL_checkstring(L, 2);
1064 ServerActiveObject *co = getobject(ref);
1065 if(co == NULL) return 0;
1067 const char *itemstring = lua_tostring(L, 2);
1068 infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
1069 <<" itemstring=\""<<itemstring<<"\""<<std::endl;
1071 std::istringstream is(itemstring, std::ios::binary);
1072 ServerEnvironment *env = co->getEnv();
1074 IGameDef *gamedef = env->getGameDef();
1075 InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
1076 infostream<<"item="<<env<<std::endl;
1077 bool fits = co->addToInventory(item);
1079 lua_pushboolean(L, fits);
1084 ObjectRef(ServerActiveObject *object):
1087 //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1093 infostream<<"ObjectRef destructing for id="
1094 <<m_object->getId()<<std::endl;
1096 infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1099 // Creates an ObjectRef and leaves it on top of stack
1100 // Not callable from Lua; all references are created on the C side.
1101 static void create(lua_State *L, ServerActiveObject *object)
1103 ObjectRef *o = new ObjectRef(object);
1104 //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1105 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1106 luaL_getmetatable(L, className);
1107 lua_setmetatable(L, -2);
1110 static void set_null(lua_State *L)
1112 ObjectRef *o = checkobject(L, -1);
1116 static void Register(lua_State *L)
1119 int methodtable = lua_gettop(L);
1120 luaL_newmetatable(L, className);
1121 int metatable = lua_gettop(L);
1123 lua_pushliteral(L, "__metatable");
1124 lua_pushvalue(L, methodtable);
1125 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1127 lua_pushliteral(L, "__index");
1128 lua_pushvalue(L, methodtable);
1129 lua_settable(L, metatable);
1131 lua_pushliteral(L, "__gc");
1132 lua_pushcfunction(L, gc_object);
1133 lua_settable(L, metatable);
1135 lua_pop(L, 1); // drop metatable
1137 luaL_openlib(L, 0, methods, 0); // fill methodtable
1138 lua_pop(L, 1); // drop methodtable
1140 // Cannot be created from Lua
1141 //lua_register(L, className, create_object);
1144 const char ObjectRef::className[] = "ObjectRef";
1145 const luaL_reg ObjectRef::methods[] = {
1146 method(ObjectRef, remove),
1147 method(ObjectRef, getpos),
1148 method(ObjectRef, setpos),
1149 method(ObjectRef, moveto),
1150 method(ObjectRef, setvelocity),
1151 method(ObjectRef, setacceleration),
1152 method(ObjectRef, add_to_inventory),
1156 // Creates a new anonymous reference if id=0
1157 static void objectref_get_or_create(lua_State *L,
1158 ServerActiveObject *cobj)
1160 if(cobj->getId() == 0){
1161 ObjectRef::create(L, cobj);
1163 objectref_get(L, cobj->getId());
1168 Main export function
1171 void scriptapi_export(lua_State *L, Server *server)
1174 assert(lua_checkstack(L, 20));
1175 infostream<<"scriptapi_export"<<std::endl;
1176 StackUnroller stack_unroller(L);
1178 // Store server as light userdata in registry
1179 lua_pushlightuserdata(L, server);
1180 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
1182 // Register global functions in table minetest
1184 luaL_register(L, NULL, minetest_f);
1185 lua_setglobal(L, "minetest");
1187 // Get the main minetest table
1188 lua_getglobal(L, "minetest");
1190 // Add tables to minetest
1193 lua_setfield(L, -2, "registered_blocks");*/
1196 lua_setfield(L, -2, "registered_entities");
1199 lua_setfield(L, -2, "registered_globalsteps");
1202 lua_setfield(L, -2, "registered_on_placenodes");
1205 lua_setfield(L, -2, "registered_on_dignodes");
1208 lua_setfield(L, -2, "registered_on_punchnodes");
1211 lua_setfield(L, -2, "object_refs");
1214 lua_setfield(L, -2, "luaentities");
1216 // Create entity prototype
1217 luaL_newmetatable(L, "minetest.entity");
1218 // metatable.__index = metatable
1219 lua_pushvalue(L, -1); // Duplicate metatable
1220 lua_setfield(L, -2, "__index");
1221 // Put functions in metatable
1222 luaL_register(L, NULL, minetest_entity_m);
1223 // Put other stuff in metatable
1225 // Environment C reference
1226 EnvRef::Register(L);
1228 // Object C reference
1229 ObjectRef::Register(L);
1232 void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
1235 assert(lua_checkstack(L, 20));
1236 infostream<<"scriptapi_add_environment"<<std::endl;
1237 StackUnroller stack_unroller(L);
1239 // Create EnvRef on stack
1240 EnvRef::create(L, env);
1241 int envref = lua_gettop(L);
1243 // minetest.env = envref
1244 lua_getglobal(L, "minetest");
1245 luaL_checktype(L, -1, LUA_TTABLE);
1246 lua_pushvalue(L, envref);
1247 lua_setfield(L, -2, "env");
1251 // Dump stack top with the dump2 function
1252 static void dump2(lua_State *L, const char *name)
1254 // Dump object (debug)
1255 lua_getglobal(L, "dump2");
1256 luaL_checktype(L, -1, LUA_TFUNCTION);
1257 lua_pushvalue(L, -2); // Get previous stack top as first parameter
1258 lua_pushstring(L, name);
1259 if(lua_pcall(L, 2, 0, 0))
1260 script_error(L, "error: %s\n", lua_tostring(L, -1));
1268 void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
1271 assert(lua_checkstack(L, 20));
1272 infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
1273 StackUnroller stack_unroller(L);
1275 // Create object on stack
1276 ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
1277 int object = lua_gettop(L);
1279 // Get minetest.object_refs table
1280 lua_getglobal(L, "minetest");
1281 lua_getfield(L, -1, "object_refs");
1282 luaL_checktype(L, -1, LUA_TTABLE);
1283 int objectstable = lua_gettop(L);
1285 // object_refs[id] = object
1286 lua_pushnumber(L, cobj->getId()); // Push id
1287 lua_pushvalue(L, object); // Copy object to top of stack
1288 lua_settable(L, objectstable);
1291 void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
1294 assert(lua_checkstack(L, 20));
1295 infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
1296 StackUnroller stack_unroller(L);
1298 // Get minetest.object_refs table
1299 lua_getglobal(L, "minetest");
1300 lua_getfield(L, -1, "object_refs");
1301 luaL_checktype(L, -1, LUA_TTABLE);
1302 int objectstable = lua_gettop(L);
1304 // Get object_refs[id]
1305 lua_pushnumber(L, cobj->getId()); // Push id
1306 lua_gettable(L, objectstable);
1307 // Set object reference to NULL
1308 ObjectRef::set_null(L);
1309 lua_pop(L, 1); // pop object
1311 // Set object_refs[id] = nil
1312 lua_pushnumber(L, cobj->getId()); // Push id
1314 lua_settable(L, objectstable);
1321 void scriptapi_environment_step(lua_State *L, float dtime)
1324 assert(lua_checkstack(L, 20));
1325 //infostream<<"scriptapi_environment_step"<<std::endl;
1326 StackUnroller stack_unroller(L);
1328 // Get minetest.registered_globalsteps
1329 lua_getglobal(L, "minetest");
1330 lua_getfield(L, -1, "registered_globalsteps");
1331 luaL_checktype(L, -1, LUA_TTABLE);
1332 int table = lua_gettop(L);
1335 while(lua_next(L, table) != 0){
1336 // key at index -2 and value at index -1
1337 luaL_checktype(L, -1, LUA_TFUNCTION);
1339 lua_pushnumber(L, dtime);
1340 if(lua_pcall(L, 1, 0, 0))
1341 script_error(L, "error: %s\n", lua_tostring(L, -1));
1342 // value removed, keep key for next iteration
1346 void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode)
1349 assert(lua_checkstack(L, 20));
1350 //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
1351 StackUnroller stack_unroller(L);
1353 // Get server from registry
1354 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1355 Server *server = (Server*)lua_touserdata(L, -1);
1356 // And get the writable node definition manager from the server
1357 IWritableNodeDefManager *ndef =
1358 server->getWritableNodeDefManager();
1360 // Get minetest.registered_on_placenodes
1361 lua_getglobal(L, "minetest");
1362 lua_getfield(L, -1, "registered_on_placenodes");
1363 luaL_checktype(L, -1, LUA_TTABLE);
1364 int table = lua_gettop(L);
1367 while(lua_next(L, table) != 0){
1368 // key at index -2 and value at index -1
1369 luaL_checktype(L, -1, LUA_TFUNCTION);
1372 pushnode(L, newnode, ndef);
1373 if(lua_pcall(L, 2, 0, 0))
1374 script_error(L, "error: %s\n", lua_tostring(L, -1));
1375 // value removed, keep key for next iteration
1379 void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode)
1382 assert(lua_checkstack(L, 20));
1383 //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
1384 StackUnroller stack_unroller(L);
1386 // Get server from registry
1387 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1388 Server *server = (Server*)lua_touserdata(L, -1);
1389 // And get the writable node definition manager from the server
1390 IWritableNodeDefManager *ndef =
1391 server->getWritableNodeDefManager();
1393 // Get minetest.registered_on_dignodes
1394 lua_getglobal(L, "minetest");
1395 lua_getfield(L, -1, "registered_on_dignodes");
1396 luaL_checktype(L, -1, LUA_TTABLE);
1397 int table = lua_gettop(L);
1400 while(lua_next(L, table) != 0){
1401 // key at index -2 and value at index -1
1402 luaL_checktype(L, -1, LUA_TFUNCTION);
1405 pushnode(L, oldnode, ndef);
1406 if(lua_pcall(L, 2, 0, 0))
1407 script_error(L, "error: %s\n", lua_tostring(L, -1));
1408 // value removed, keep key for next iteration
1412 void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode oldnode)
1415 assert(lua_checkstack(L, 20));
1416 //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
1417 StackUnroller stack_unroller(L);
1419 // Get server from registry
1420 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
1421 Server *server = (Server*)lua_touserdata(L, -1);
1422 // And get the writable node definition manager from the server
1423 IWritableNodeDefManager *ndef =
1424 server->getWritableNodeDefManager();
1426 // Get minetest.registered_on_punchnodes
1427 lua_getglobal(L, "minetest");
1428 lua_getfield(L, -1, "registered_on_punchnodes");
1429 luaL_checktype(L, -1, LUA_TTABLE);
1430 int table = lua_gettop(L);
1433 while(lua_next(L, table) != 0){
1434 // key at index -2 and value at index -1
1435 luaL_checktype(L, -1, LUA_TFUNCTION);
1438 pushnode(L, oldnode, ndef);
1439 if(lua_pcall(L, 2, 0, 0))
1440 script_error(L, "error: %s\n", lua_tostring(L, -1));
1441 // value removed, keep key for next iteration
1449 bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
1450 const std::string &staticdata)
1453 assert(lua_checkstack(L, 20));
1454 infostream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
1455 <<name<<"\""<<std::endl;
1456 StackUnroller stack_unroller(L);
1458 // Get minetest.registered_entities[name]
1459 lua_getglobal(L, "minetest");
1460 lua_getfield(L, -1, "registered_entities");
1461 luaL_checktype(L, -1, LUA_TTABLE);
1462 lua_pushstring(L, name);
1463 lua_gettable(L, -2);
1464 // Should be a table, which we will use as a prototype
1465 //luaL_checktype(L, -1, LUA_TTABLE);
1466 if(lua_type(L, -1) != LUA_TTABLE){
1467 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
1470 int prototype_table = lua_gettop(L);
1471 //dump2(L, "prototype_table");
1473 // Create entity object
1475 int object = lua_gettop(L);
1477 // Set object metatable
1478 lua_pushvalue(L, prototype_table);
1479 lua_setmetatable(L, -2);
1481 // Add object reference
1482 // This should be userdata with metatable ObjectRef
1483 objectref_get(L, id);
1484 luaL_checktype(L, -1, LUA_TUSERDATA);
1485 if(!luaL_checkudata(L, -1, "ObjectRef"))
1486 luaL_typerror(L, -1, "ObjectRef");
1487 lua_setfield(L, -2, "object");
1489 // minetest.luaentities[id] = object
1490 lua_getglobal(L, "minetest");
1491 lua_getfield(L, -1, "luaentities");
1492 luaL_checktype(L, -1, LUA_TTABLE);
1493 lua_pushnumber(L, id); // Push id
1494 lua_pushvalue(L, object); // Copy object to top of stack
1495 lua_settable(L, -3);
1497 // Get on_activate function
1498 lua_pushvalue(L, object);
1499 lua_getfield(L, -1, "on_activate");
1500 if(!lua_isnil(L, -1)){
1501 luaL_checktype(L, -1, LUA_TFUNCTION);
1502 lua_pushvalue(L, object); // self
1503 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
1504 // Call with 2 arguments, 0 results
1505 if(lua_pcall(L, 2, 0, 0))
1506 script_error(L, "error running function %s:on_activate: %s\n",
1507 name, lua_tostring(L, -1));
1513 void scriptapi_luaentity_rm(lua_State *L, u16 id)
1516 assert(lua_checkstack(L, 20));
1517 infostream<<"scriptapi_luaentity_rm: id="<<id<<std::endl;
1519 // Get minetest.luaentities table
1520 lua_getglobal(L, "minetest");
1521 lua_getfield(L, -1, "luaentities");
1522 luaL_checktype(L, -1, LUA_TTABLE);
1523 int objectstable = lua_gettop(L);
1525 // Set luaentities[id] = nil
1526 lua_pushnumber(L, id); // Push id
1528 lua_settable(L, objectstable);
1530 lua_pop(L, 2); // pop luaentities, minetest
1533 std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
1536 assert(lua_checkstack(L, 20));
1537 infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
1538 StackUnroller stack_unroller(L);
1540 // Get minetest.luaentities[id]
1541 luaentity_get(L, id);
1542 int object = lua_gettop(L);
1544 // Get get_staticdata function
1545 lua_pushvalue(L, object);
1546 lua_getfield(L, -1, "get_staticdata");
1547 if(lua_isnil(L, -1))
1550 luaL_checktype(L, -1, LUA_TFUNCTION);
1551 lua_pushvalue(L, object); // self
1552 // Call with 1 arguments, 1 results
1553 if(lua_pcall(L, 1, 1, 0))
1554 script_error(L, "error running function get_staticdata: %s\n",
1555 lua_tostring(L, -1));
1558 const char *s = lua_tolstring(L, -1, &len);
1559 return std::string(s, len);
1562 void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
1563 LuaEntityProperties *prop)
1566 assert(lua_checkstack(L, 20));
1567 infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
1568 StackUnroller stack_unroller(L);
1570 // Get minetest.luaentities[id]
1571 luaentity_get(L, id);
1572 //int object = lua_gettop(L);
1574 lua_getfield(L, -1, "physical");
1575 if(lua_isboolean(L, -1))
1576 prop->physical = lua_toboolean(L, -1);
1579 lua_getfield(L, -1, "weight");
1580 prop->weight = lua_tonumber(L, -1);
1583 lua_getfield(L, -1, "collisionbox");
1584 if(lua_istable(L, -1)){
1585 lua_rawgeti(L, -1, 1);
1586 prop->collisionbox.MinEdge.X = lua_tonumber(L, -1);
1588 lua_rawgeti(L, -1, 2);
1589 prop->collisionbox.MinEdge.Y = lua_tonumber(L, -1);
1591 lua_rawgeti(L, -1, 3);
1592 prop->collisionbox.MinEdge.Z = lua_tonumber(L, -1);
1594 lua_rawgeti(L, -1, 4);
1595 prop->collisionbox.MaxEdge.X = lua_tonumber(L, -1);
1597 lua_rawgeti(L, -1, 5);
1598 prop->collisionbox.MaxEdge.Y = lua_tonumber(L, -1);
1600 lua_rawgeti(L, -1, 6);
1601 prop->collisionbox.MaxEdge.Z = lua_tonumber(L, -1);
1606 lua_getfield(L, -1, "visual");
1607 if(lua_isstring(L, -1))
1608 prop->visual = lua_tostring(L, -1);
1611 lua_getfield(L, -1, "textures");
1612 if(lua_istable(L, -1)){
1613 prop->textures.clear();
1614 int table = lua_gettop(L);
1616 while(lua_next(L, table) != 0){
1617 // key at index -2 and value at index -1
1618 if(lua_isstring(L, -1))
1619 prop->textures.push_back(lua_tostring(L, -1));
1621 prop->textures.push_back("");
1622 // removes value, keeps key for next iteration
1630 void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
1633 assert(lua_checkstack(L, 20));
1634 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1635 StackUnroller stack_unroller(L);
1637 // Get minetest.luaentities[id]
1638 luaentity_get(L, id);
1639 int object = lua_gettop(L);
1640 // State: object is at top of stack
1641 // Get step function
1642 lua_getfield(L, -1, "on_step");
1643 if(lua_isnil(L, -1))
1645 luaL_checktype(L, -1, LUA_TFUNCTION);
1646 lua_pushvalue(L, object); // self
1647 lua_pushnumber(L, dtime); // dtime
1648 // Call with 2 arguments, 0 results
1649 if(lua_pcall(L, 2, 0, 0))
1650 script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
1653 // Calls entity:on_punch(ObjectRef puncher)
1654 void scriptapi_luaentity_punch(lua_State *L, u16 id,
1655 ServerActiveObject *puncher)
1658 assert(lua_checkstack(L, 20));
1659 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1660 StackUnroller stack_unroller(L);
1662 // Get minetest.luaentities[id]
1663 luaentity_get(L, id);
1664 int object = lua_gettop(L);
1665 // State: object is at top of stack
1667 lua_getfield(L, -1, "on_punch");
1668 if(lua_isnil(L, -1))
1670 luaL_checktype(L, -1, LUA_TFUNCTION);
1671 lua_pushvalue(L, object); // self
1672 objectref_get_or_create(L, puncher); // Clicker reference
1673 // Call with 2 arguments, 0 results
1674 if(lua_pcall(L, 2, 0, 0))
1675 script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
1678 // Calls entity:on_rightclick(ObjectRef clicker)
1679 void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
1680 ServerActiveObject *clicker)
1683 assert(lua_checkstack(L, 20));
1684 //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
1685 StackUnroller stack_unroller(L);
1687 // Get minetest.luaentities[id]
1688 luaentity_get(L, id);
1689 int object = lua_gettop(L);
1690 // State: object is at top of stack
1692 lua_getfield(L, -1, "on_rightclick");
1693 if(lua_isnil(L, -1))
1695 luaL_checktype(L, -1, LUA_TFUNCTION);
1696 lua_pushvalue(L, object); // self
1697 objectref_get_or_create(L, clicker); // Clicker reference
1698 // Call with 2 arguments, 0 results
1699 if(lua_pcall(L, 2, 0, 0))
1700 script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));