3 Copyright (C) 2013 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 Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser 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"
30 #include "settings.h" // For accessing g_settings
31 #include "main.h" // For g_settings
36 #include "scriptapi_types.h"
37 #include "scriptapi_env.h"
38 #include "scriptapi_nodetimer.h"
39 #include "scriptapi_inventory.h"
40 #include "scriptapi_nodemeta.h"
41 #include "scriptapi_object.h"
42 #include "scriptapi_noise.h"
43 #include "scriptapi_common.h"
44 #include "scriptapi_item.h"
45 #include "scriptapi_content.h"
46 #include "scriptapi_craft.h"
48 /*****************************************************************************/
50 /*****************************************************************************/
57 ModNameStorer(lua_State *L_, const std::string modname):
60 // Store current modname in registry
61 lua_pushstring(L, modname.c_str());
62 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
66 // Clear current modname in registry
68 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
72 bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
73 const std::string &modname)
75 ModNameStorer modnamestorer(L, modname);
77 if(!string_allowed(modname, "abcdefghijklmnopqrstuvwxyz"
79 errorstream<<"Error loading mod \""<<modname
80 <<"\": modname does not follow naming conventions: "
81 <<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
88 success = script_load(L, scriptpath.c_str());
91 errorstream<<"Error loading mod \""<<modname
92 <<"\": "<<e.what()<<std::endl;
99 /*****************************************************************************/
101 /*****************************************************************************/
106 static void read_privileges(lua_State *L, int index,
107 std::set<std::string> &result)
113 while(lua_next(L, index) != 0){
114 // key at index -2 and value at index -1
115 std::string key = luaL_checkstring(L, -2);
116 bool value = lua_toboolean(L, -1);
119 // removes value, keeps key for next iteration
124 static void get_auth_handler(lua_State *L)
126 lua_getglobal(L, "minetest");
127 lua_getfield(L, -1, "registered_auth_handler");
128 if(lua_isnil(L, -1)){
130 lua_getfield(L, -1, "builtin_auth_handler");
132 if(lua_type(L, -1) != LUA_TTABLE)
133 throw LuaError(L, "Authentication handler table not valid");
136 bool scriptapi_get_auth(lua_State *L, const std::string &playername,
137 std::string *dst_password, std::set<std::string> *dst_privs)
140 assert(lua_checkstack(L, 20));
141 StackUnroller stack_unroller(L);
144 lua_getfield(L, -1, "get_auth");
145 if(lua_type(L, -1) != LUA_TFUNCTION)
146 throw LuaError(L, "Authentication handler missing get_auth");
147 lua_pushstring(L, playername.c_str());
148 if(lua_pcall(L, 1, 1, 0))
149 script_error(L, "error: %s", lua_tostring(L, -1));
151 // nil = login not allowed
154 luaL_checktype(L, -1, LUA_TTABLE);
156 std::string password;
157 bool found = getstringfield(L, -1, "password", password);
159 throw LuaError(L, "Authentication handler didn't return password");
161 *dst_password = password;
163 lua_getfield(L, -1, "privileges");
164 if(!lua_istable(L, -1))
166 "Authentication handler didn't return privilege table");
168 read_privileges(L, -1, *dst_privs);
174 void scriptapi_create_auth(lua_State *L, const std::string &playername,
175 const std::string &password)
178 assert(lua_checkstack(L, 20));
179 StackUnroller stack_unroller(L);
182 lua_getfield(L, -1, "create_auth");
183 if(lua_type(L, -1) != LUA_TFUNCTION)
184 throw LuaError(L, "Authentication handler missing create_auth");
185 lua_pushstring(L, playername.c_str());
186 lua_pushstring(L, password.c_str());
187 if(lua_pcall(L, 2, 0, 0))
188 script_error(L, "error: %s", lua_tostring(L, -1));
191 bool scriptapi_set_password(lua_State *L, const std::string &playername,
192 const std::string &password)
195 assert(lua_checkstack(L, 20));
196 StackUnroller stack_unroller(L);
199 lua_getfield(L, -1, "set_password");
200 if(lua_type(L, -1) != LUA_TFUNCTION)
201 throw LuaError(L, "Authentication handler missing set_password");
202 lua_pushstring(L, playername.c_str());
203 lua_pushstring(L, password.c_str());
204 if(lua_pcall(L, 2, 1, 0))
205 script_error(L, "error: %s", lua_tostring(L, -1));
206 return lua_toboolean(L, -1);
209 /*****************************************************************************/
211 /*****************************************************************************/
215 void read_groups(lua_State *L, int index,
216 std::map<std::string, int> &result)
218 if (!lua_istable(L,index))
224 while(lua_next(L, index) != 0){
225 // key at index -2 and value at index -1
226 std::string name = luaL_checkstring(L, -2);
227 int rating = luaL_checkinteger(L, -1);
228 result[name] = rating;
229 // removes value, keeps key for next iteration
234 struct EnumString es_BiomeTerrainType[] =
236 {BIOME_TERRAIN_NORMAL, "normal"},
237 {BIOME_TERRAIN_LIQUID, "liquid"},
238 {BIOME_TERRAIN_NETHER, "nether"},
239 {BIOME_TERRAIN_AETHER, "aether"},
240 {BIOME_TERRAIN_FLAT, "flat"},
244 /*****************************************************************************/
246 /*****************************************************************************/
251 static void set_dig_params(lua_State *L, int table,
252 const DigParams ¶ms)
254 setboolfield(L, table, "diggable", params.diggable);
255 setfloatfield(L, table, "time", params.time);
256 setintfield(L, table, "wear", params.wear);
259 static void push_dig_params(lua_State *L,
260 const DigParams ¶ms)
263 set_dig_params(L, -1, params);
270 static void set_hit_params(lua_State *L, int table,
271 const HitParams ¶ms)
273 setintfield(L, table, "hp", params.hp);
274 setintfield(L, table, "wear", params.wear);
277 static void push_hit_params(lua_State *L,
278 const HitParams ¶ms)
281 set_hit_params(L, -1, params);
288 static void read_server_sound_params(lua_State *L, int index,
289 ServerSoundParams ¶ms)
292 index = lua_gettop(L) + 1 + index;
294 params = ServerSoundParams();
295 if(lua_istable(L, index)){
296 getfloatfield(L, index, "gain", params.gain);
297 getstringfield(L, index, "to_player", params.to_player);
298 lua_getfield(L, index, "pos");
299 if(!lua_isnil(L, -1)){
300 v3f p = read_v3f(L, -1)*BS;
302 params.type = ServerSoundParams::SSP_POSITIONAL;
305 lua_getfield(L, index, "object");
306 if(!lua_isnil(L, -1)){
307 ObjectRef *ref = ObjectRef::checkobject(L, -1);
308 ServerActiveObject *sao = ObjectRef::getobject(ref);
310 params.object = sao->getId();
311 params.type = ServerSoundParams::SSP_OBJECT;
315 params.max_hear_distance = BS*getfloatfield_default(L, index,
316 "max_hear_distance", params.max_hear_distance/BS);
317 getboolfield(L, index, "loop", params.loop);
321 /*****************************************************************************/
323 /*****************************************************************************/
325 // Push the list of callbacks (a lua table).
326 // Then push nargs arguments.
327 // Then call this function, which
328 // - runs the callbacks
329 // - removes the table and arguments from the lua stack
330 // - pushes the return value, computed depending on mode
331 void scriptapi_run_callbacks(lua_State *L, int nargs,
332 RunCallbacksMode mode)
334 // Insert the return value into the lua stack, below the table
335 assert(lua_gettop(L) >= nargs + 1);
337 lua_insert(L, -(nargs + 1) - 1);
338 // Stack now looks like this:
339 // ... <return value = nil> <table> <arg#1> <arg#2> ... <arg#n>
341 int rv = lua_gettop(L) - nargs - 1;
345 luaL_checktype(L, table, LUA_TTABLE);
349 bool first_loop = true;
350 while(lua_next(L, table) != 0){
351 // key at index -2 and value at index -1
352 luaL_checktype(L, -1, LUA_TFUNCTION);
354 for(int i = 0; i < nargs; i++)
355 lua_pushvalue(L, arg+i);
356 if(lua_pcall(L, nargs, 1, 0))
357 script_error(L, "error: %s", lua_tostring(L, -1));
359 // Move return value to designated space in stack
362 // Result of first callback is always moved
366 // Otherwise, what happens depends on the mode
367 if(mode == RUN_CALLBACKS_MODE_FIRST)
369 else if(mode == RUN_CALLBACKS_MODE_LAST)
371 else if(mode == RUN_CALLBACKS_MODE_AND ||
372 mode == RUN_CALLBACKS_MODE_AND_SC){
373 if((bool)lua_toboolean(L, rv) == true &&
374 (bool)lua_toboolean(L, -1) == false)
379 else if(mode == RUN_CALLBACKS_MODE_OR ||
380 mode == RUN_CALLBACKS_MODE_OR_SC){
381 if((bool)lua_toboolean(L, rv) == false &&
382 (bool)lua_toboolean(L, -1) == true)
391 // Handle short circuit modes
392 if(mode == RUN_CALLBACKS_MODE_AND_SC &&
393 (bool)lua_toboolean(L, rv) == false)
395 else if(mode == RUN_CALLBACKS_MODE_OR_SC &&
396 (bool)lua_toboolean(L, rv) == true)
399 // value removed, keep key for next iteration
402 // Remove stuff from stack, leaving only the return value
405 // Fix return value in case no callbacks were called
407 if(mode == RUN_CALLBACKS_MODE_AND ||
408 mode == RUN_CALLBACKS_MODE_AND_SC){
410 lua_pushboolean(L, true);
412 else if(mode == RUN_CALLBACKS_MODE_OR ||
413 mode == RUN_CALLBACKS_MODE_OR_SC){
415 lua_pushboolean(L, false);
420 bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
421 const std::string &message)
424 assert(lua_checkstack(L, 20));
425 StackUnroller stack_unroller(L);
427 // Get minetest.registered_on_chat_messages
428 lua_getglobal(L, "minetest");
429 lua_getfield(L, -1, "registered_on_chat_messages");
431 lua_pushstring(L, name.c_str());
432 lua_pushstring(L, message.c_str());
433 scriptapi_run_callbacks(L, 2, RUN_CALLBACKS_MODE_OR_SC);
434 bool ate = lua_toboolean(L, -1);
438 void scriptapi_on_shutdown(lua_State *L)
441 assert(lua_checkstack(L, 20));
442 StackUnroller stack_unroller(L);
444 // Get registered shutdown hooks
445 lua_getglobal(L, "minetest");
446 lua_getfield(L, -1, "registered_on_shutdown");
448 scriptapi_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST);
451 void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
454 assert(lua_checkstack(L, 20));
455 StackUnroller stack_unroller(L);
457 // Get minetest.registered_on_newplayers
458 lua_getglobal(L, "minetest");
459 lua_getfield(L, -1, "registered_on_newplayers");
461 objectref_get_or_create(L, player);
462 scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
465 void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player)
468 assert(lua_checkstack(L, 20));
469 StackUnroller stack_unroller(L);
471 // Get minetest.registered_on_dieplayers
472 lua_getglobal(L, "minetest");
473 lua_getfield(L, -1, "registered_on_dieplayers");
475 objectref_get_or_create(L, player);
476 scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
479 bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
482 assert(lua_checkstack(L, 20));
483 StackUnroller stack_unroller(L);
485 // Get minetest.registered_on_respawnplayers
486 lua_getglobal(L, "minetest");
487 lua_getfield(L, -1, "registered_on_respawnplayers");
489 objectref_get_or_create(L, player);
490 scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR);
491 bool positioning_handled_by_some = lua_toboolean(L, -1);
492 return positioning_handled_by_some;
495 void scriptapi_on_joinplayer(lua_State *L, ServerActiveObject *player)
498 assert(lua_checkstack(L, 20));
499 StackUnroller stack_unroller(L);
501 // Get minetest.registered_on_joinplayers
502 lua_getglobal(L, "minetest");
503 lua_getfield(L, -1, "registered_on_joinplayers");
505 objectref_get_or_create(L, player);
506 scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
509 void scriptapi_on_leaveplayer(lua_State *L, ServerActiveObject *player)
512 assert(lua_checkstack(L, 20));
513 StackUnroller stack_unroller(L);
515 // Get minetest.registered_on_leaveplayers
516 lua_getglobal(L, "minetest");
517 lua_getfield(L, -1, "registered_on_leaveplayers");
519 objectref_get_or_create(L, player);
520 scriptapi_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST);
526 void scriptapi_on_player_receive_fields(lua_State *L,
527 ServerActiveObject *player,
528 const std::string &formname,
529 const std::map<std::string, std::string> &fields)
532 assert(lua_checkstack(L, 20));
533 StackUnroller stack_unroller(L);
535 // Get minetest.registered_on_chat_messages
536 lua_getglobal(L, "minetest");
537 lua_getfield(L, -1, "registered_on_player_receive_fields");
540 objectref_get_or_create(L, player);
542 lua_pushstring(L, formname.c_str());
545 for(std::map<std::string, std::string>::const_iterator
546 i = fields.begin(); i != fields.end(); i++){
547 const std::string &name = i->first;
548 const std::string &value = i->second;
549 lua_pushstring(L, name.c_str());
550 lua_pushlstring(L, value.c_str(), value.size());
553 scriptapi_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC);
555 /*****************************************************************************/
557 /*****************************************************************************/
560 // Writes a line to dstream
561 static int l_debug(lua_State *L)
563 std::string text = lua_tostring(L, 1);
564 dstream << text << std::endl;
568 // log([level,] text)
569 // Writes a line to the logger.
570 // The one-argument version logs to infostream.
571 // The two-argument version accept a log level: error, action, info, or verbose.
572 static int l_log(lua_State *L)
575 LogMessageLevel level = LMT_INFO;
578 text = lua_tostring(L, 1);
582 std::string levelname = luaL_checkstring(L, 1);
583 text = luaL_checkstring(L, 2);
584 if(levelname == "error")
586 else if(levelname == "action")
588 else if(levelname == "verbose")
591 log_printline(level, text);
595 // request_shutdown()
596 static int l_request_shutdown(lua_State *L)
598 get_server(L)->requestShutdown();
602 // get_server_status()
603 static int l_get_server_status(lua_State *L)
605 lua_pushstring(L, wide_to_narrow(get_server(L)->getStatusString()).c_str());
609 // register_biome_groups({frequencies})
610 static int l_register_biome_groups(lua_State *L)
612 luaL_checktype(L, 1, LUA_TTABLE);
614 if (!lua_istable(L, index))
615 throw LuaError(L, "register_biome_groups: parameter is not a table");
617 BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
619 verbosestream << "register_biome_groups: BiomeDefManager not active" << std::endl;
624 for (int i = 1; lua_next(L, index) != 0; i++) {
625 bmgr->addBiomeGroup(lua_tonumber(L, -1));
633 // register_biome({lots of stuff})
634 static int l_register_biome(lua_State *L)
636 luaL_checktype(L, 1, LUA_TTABLE);
637 int index = 1, groupid;
638 std::string nodename;
640 IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager();
641 BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
643 verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
647 groupid = getintfield_default(L, index, "group_id", 0);
649 enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
650 "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
651 Biome *b = bmgr->createBiome(terrain);
653 b->name = getstringfield_default(L, index, "name", "");
655 if (getstringfield(L, index, "node_top", nodename))
656 b->n_top = MapNode(ndef->getId(nodename));
658 b->n_top = MapNode(CONTENT_IGNORE);
660 if (getstringfield(L, index, "node_filler", nodename))
661 b->n_filler = MapNode(ndef->getId(nodename));
663 b->n_filler = b->n_top;
665 b->ntopnodes = getintfield_default(L, index, "num_top_nodes", 0);
667 b->height_min = getintfield_default(L, index, "height_min", 0);
668 b->height_max = getintfield_default(L, index, "height_max", 0);
669 b->heat_min = getfloatfield_default(L, index, "heat_min", 0.);
670 b->heat_max = getfloatfield_default(L, index, "heat_max", 0.);
671 b->humidity_min = getfloatfield_default(L, index, "humidity_min", 0.);
672 b->humidity_max = getfloatfield_default(L, index, "humidity_max", 0.);
674 b->np = new NoiseParams; // should read an entire NoiseParams later on...
675 getfloatfield(L, index, "scale", b->np->scale);
676 getfloatfield(L, index, "offset", b->np->offset);
678 b->groupid = (s8)groupid;
679 b->flags = 0; //reserved
683 verbosestream << "register_biome: " << b->name << std::endl;
689 // setting_set(name, value)
690 static int l_setting_set(lua_State *L)
692 const char *name = luaL_checkstring(L, 1);
693 const char *value = luaL_checkstring(L, 2);
694 g_settings->set(name, value);
699 static int l_setting_get(lua_State *L)
701 const char *name = luaL_checkstring(L, 1);
703 std::string value = g_settings->get(name);
704 lua_pushstring(L, value.c_str());
705 } catch(SettingNotFoundException &e){
711 // setting_getbool(name)
712 static int l_setting_getbool(lua_State *L)
714 const char *name = luaL_checkstring(L, 1);
716 bool value = g_settings->getBool(name);
717 lua_pushboolean(L, value);
718 } catch(SettingNotFoundException &e){
725 static int l_setting_save(lua_State *L)
727 get_server(L)->saveConfig();
731 // chat_send_all(text)
732 static int l_chat_send_all(lua_State *L)
734 const char *text = luaL_checkstring(L, 1);
735 // Get server from registry
736 Server *server = get_server(L);
738 server->notifyPlayers(narrow_to_wide(text));
742 // chat_send_player(name, text)
743 static int l_chat_send_player(lua_State *L)
745 const char *name = luaL_checkstring(L, 1);
746 const char *text = luaL_checkstring(L, 2);
747 // Get server from registry
748 Server *server = get_server(L);
750 server->notifyPlayer(name, narrow_to_wide(text));
754 // get_player_privs(name, text)
755 static int l_get_player_privs(lua_State *L)
757 const char *name = luaL_checkstring(L, 1);
758 // Get server from registry
759 Server *server = get_server(L);
762 int table = lua_gettop(L);
763 std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
764 for(std::set<std::string>::const_iterator
765 i = privs_s.begin(); i != privs_s.end(); i++){
766 lua_pushboolean(L, true);
767 lua_setfield(L, table, i->c_str());
769 lua_pushvalue(L, table);
774 static int l_get_ban_list(lua_State *L)
776 lua_pushstring(L, get_server(L)->getBanDescription("").c_str());
780 // get_ban_description()
781 static int l_get_ban_description(lua_State *L)
783 const char * ip_or_name = luaL_checkstring(L, 1);
784 lua_pushstring(L, get_server(L)->getBanDescription(std::string(ip_or_name)).c_str());
789 static int l_ban_player(lua_State *L)
791 const char * name = luaL_checkstring(L, 1);
792 Player *player = get_env(L)->getPlayer(name);
795 lua_pushboolean(L, false); // no such player
800 Address addr = get_server(L)->getPeerAddress(get_env(L)->getPlayer(name)->peer_id);
801 std::string ip_str = addr.serializeString();
802 get_server(L)->setIpBanned(ip_str, name);
804 catch(con::PeerNotFoundException) // unlikely
806 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
807 lua_pushboolean(L, false); // error
810 lua_pushboolean(L, true);
814 // unban_player_or_ip()
815 static int l_unban_player_of_ip(lua_State *L)
817 const char * ip_or_name = luaL_checkstring(L, 1);
818 get_server(L)->unsetIpBanned(ip_or_name);
819 lua_pushboolean(L, true);
823 // show_formspec(playername,formname,formspec)
824 static int l_show_formspec(lua_State *L)
826 const char *playername = luaL_checkstring(L, 1);
827 const char *formname = luaL_checkstring(L, 2);
828 const char *formspec = luaL_checkstring(L, 3);
830 if(get_server(L)->showFormspec(playername,formspec,formname))
832 lua_pushboolean(L, true);
834 lua_pushboolean(L, false);
839 // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
840 static int l_get_dig_params(lua_State *L)
842 std::map<std::string, int> groups;
843 read_groups(L, 1, groups);
844 ToolCapabilities tp = read_tool_capabilities(L, 2);
845 if(lua_isnoneornil(L, 3))
846 push_dig_params(L, getDigParams(groups, &tp));
848 push_dig_params(L, getDigParams(groups, &tp,
849 luaL_checknumber(L, 3)));
853 // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
854 static int l_get_hit_params(lua_State *L)
856 std::map<std::string, int> groups;
857 read_groups(L, 1, groups);
858 ToolCapabilities tp = read_tool_capabilities(L, 2);
859 if(lua_isnoneornil(L, 3))
860 push_hit_params(L, getHitParams(groups, &tp));
862 push_hit_params(L, getHitParams(groups, &tp,
863 luaL_checknumber(L, 3)));
867 // get_current_modname()
868 static int l_get_current_modname(lua_State *L)
870 lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
874 // get_modpath(modname)
875 static int l_get_modpath(lua_State *L)
877 std::string modname = luaL_checkstring(L, 1);
879 if(modname == "__builtin"){
880 std::string path = get_server(L)->getBuiltinLuaPath();
881 lua_pushstring(L, path.c_str());
884 const ModSpec *mod = get_server(L)->getModSpec(modname);
889 lua_pushstring(L, mod->path.c_str());
894 // the returned list is sorted alphabetically for you
895 static int l_get_modnames(lua_State *L)
897 // Get a list of mods
898 core::list<std::string> mods_unsorted, mods_sorted;
899 get_server(L)->getModNames(mods_unsorted);
901 // Take unsorted items from mods_unsorted and sort them into
902 // mods_sorted; not great performance but the number of mods on a
903 // server will likely be small.
904 for(core::list<std::string>::Iterator i = mods_unsorted.begin();
905 i != mods_unsorted.end(); i++)
908 for(core::list<std::string>::Iterator x = mods_sorted.begin();
909 x != mods_unsorted.end(); x++)
911 // I doubt anybody using Minetest will be using
912 // anything not ASCII based :)
913 if((*i).compare(*x) <= 0)
915 mods_sorted.insert_before(x, *i);
921 mods_sorted.push_back(*i);
924 // Get the table insertion function from Lua.
925 lua_getglobal(L, "table");
926 lua_getfield(L, -1, "insert");
927 int insertion_func = lua_gettop(L);
929 // Package them up for Lua
931 int new_table = lua_gettop(L);
932 core::list<std::string>::Iterator i = mods_sorted.begin();
933 while(i != mods_sorted.end())
935 lua_pushvalue(L, insertion_func);
936 lua_pushvalue(L, new_table);
937 lua_pushstring(L, (*i).c_str());
938 if(lua_pcall(L, 2, 0, 0) != 0)
940 script_error(L, "error: %s", lua_tostring(L, -1));
948 static int l_get_worldpath(lua_State *L)
950 std::string worldpath = get_server(L)->getWorldPath();
951 lua_pushstring(L, worldpath.c_str());
955 // sound_play(spec, parameters)
956 static int l_sound_play(lua_State *L)
958 SimpleSoundSpec spec;
959 read_soundspec(L, 1, spec);
960 ServerSoundParams params;
961 read_server_sound_params(L, 2, params);
962 s32 handle = get_server(L)->playSound(spec, params);
963 lua_pushinteger(L, handle);
967 // sound_stop(handle)
968 static int l_sound_stop(lua_State *L)
970 int handle = luaL_checkinteger(L, 1);
971 get_server(L)->stopSound(handle);
976 static int l_is_singleplayer(lua_State *L)
978 lua_pushboolean(L, get_server(L)->isSingleplayer());
982 // get_password_hash(name, raw_password)
983 static int l_get_password_hash(lua_State *L)
985 std::string name = luaL_checkstring(L, 1);
986 std::string raw_password = luaL_checkstring(L, 2);
987 std::string hash = translatePassword(name,
988 narrow_to_wide(raw_password));
989 lua_pushstring(L, hash.c_str());
993 // notify_authentication_modified(name)
994 static int l_notify_authentication_modified(lua_State *L)
996 std::string name = "";
997 if(lua_isstring(L, 1))
998 name = lua_tostring(L, 1);
999 get_server(L)->reportPrivsModified(name);
1003 // get_craft_recipes(result item)
1004 static int l_get_all_craft_recipes(lua_State *L)
1008 std::string o_item = luaL_checkstring(L,input_i);
1009 IGameDef *gdef = get_server(L);
1010 ICraftDefManager *cdef = gdef->cdef();
1012 CraftOutput output(o_item,0);
1013 std::vector<CraftDefinition*> recipes_list = cdef->getCraftRecipes(output, gdef);
1014 if (recipes_list.empty())
1019 // Get the table insert function
1020 lua_getglobal(L, "table");
1021 lua_getfield(L, -1, "insert");
1022 int table_insert = lua_gettop(L);
1024 int table = lua_gettop(L);
1025 for(std::vector<CraftDefinition*>::const_iterator
1026 i = recipes_list.begin();
1027 i != recipes_list.end(); i++)
1032 CraftDefinition *def = *i;
1033 tmpout = def->getOutput(input, gdef);
1034 if(tmpout.item.substr(0,output.item.length()) == output.item)
1036 input = def->getInput(output, gdef);
1037 lua_pushvalue(L, table_insert);
1038 lua_pushvalue(L, table);
1042 for(std::vector<ItemStack>::const_iterator
1043 i = input.items.begin();
1044 i != input.items.end(); i++, k++)
1046 if (i->empty()) continue;
1047 sprintf(tmp,"%d",k);
1048 lua_pushstring(L,tmp);
1049 lua_pushstring(L,i->name.c_str());
1050 lua_settable(L, -3);
1052 lua_setfield(L, -2, "items");
1053 setintfield(L, -1, "width", input.width);
1054 switch (input.method)
1056 case CRAFT_METHOD_NORMAL:
1057 lua_pushstring(L,"normal");
1059 case CRAFT_METHOD_COOKING:
1060 lua_pushstring(L,"cooking");
1062 case CRAFT_METHOD_FUEL:
1063 lua_pushstring(L,"fuel");
1066 lua_pushstring(L,"unknown");
1068 lua_setfield(L, -2, "type");
1069 if(lua_pcall(L, 2, 0, 0))
1070 script_error(L, "error: %s", lua_tostring(L, -1));
1076 // rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds
1077 static int l_rollback_get_last_node_actor(lua_State *L)
1079 v3s16 p = read_v3s16(L, 1);
1080 int range = luaL_checknumber(L, 2);
1081 int seconds = luaL_checknumber(L, 3);
1082 Server *server = get_server(L);
1083 IRollbackManager *rollback = server->getRollbackManager();
1085 int act_seconds = 0;
1086 std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds);
1087 lua_pushstring(L, actor.c_str());
1088 push_v3s16(L, act_p);
1089 lua_pushnumber(L, act_seconds);
1093 // rollback_revert_actions_by(actor, seconds) -> bool, log messages
1094 static int l_rollback_revert_actions_by(lua_State *L)
1096 std::string actor = luaL_checkstring(L, 1);
1097 int seconds = luaL_checknumber(L, 2);
1098 Server *server = get_server(L);
1099 IRollbackManager *rollback = server->getRollbackManager();
1100 std::list<RollbackAction> actions = rollback->getRevertActions(actor, seconds);
1101 std::list<std::string> log;
1102 bool success = server->rollbackRevertActions(actions, &log);
1103 // Push boolean result
1104 lua_pushboolean(L, success);
1105 // Get the table insert function and push the log table
1106 lua_getglobal(L, "table");
1107 lua_getfield(L, -1, "insert");
1108 int table_insert = lua_gettop(L);
1110 int table = lua_gettop(L);
1111 for(std::list<std::string>::const_iterator i = log.begin();
1112 i != log.end(); i++)
1114 lua_pushvalue(L, table_insert);
1115 lua_pushvalue(L, table);
1116 lua_pushstring(L, i->c_str());
1117 if(lua_pcall(L, 2, 0, 0))
1118 script_error(L, "error: %s", lua_tostring(L, -1));
1120 lua_remove(L, -2); // Remove table
1121 lua_remove(L, -2); // Remove insert
1125 static const struct luaL_Reg minetest_f [] = {
1128 {"request_shutdown", l_request_shutdown},
1129 {"get_server_status", l_get_server_status},
1130 {"register_item_raw", l_register_item_raw},
1131 {"register_alias_raw", l_register_alias_raw},
1132 {"register_craft", l_register_craft},
1133 {"register_biome", l_register_biome},
1134 {"register_biome_groups", l_register_biome_groups},
1135 {"setting_set", l_setting_set},
1136 {"setting_get", l_setting_get},
1137 {"setting_getbool", l_setting_getbool},
1138 {"setting_save",l_setting_save},
1139 {"chat_send_all", l_chat_send_all},
1140 {"chat_send_player", l_chat_send_player},
1141 {"get_player_privs", l_get_player_privs},
1142 {"get_ban_list", l_get_ban_list},
1143 {"get_ban_description", l_get_ban_description},
1144 {"ban_player", l_ban_player},
1145 {"unban_player_or_ip", l_unban_player_of_ip},
1146 {"get_inventory", l_get_inventory},
1147 {"create_detached_inventory_raw", l_create_detached_inventory_raw},
1148 {"show_formspec", l_show_formspec},
1149 {"get_dig_params", l_get_dig_params},
1150 {"get_hit_params", l_get_hit_params},
1151 {"get_current_modname", l_get_current_modname},
1152 {"get_modpath", l_get_modpath},
1153 {"get_modnames", l_get_modnames},
1154 {"get_worldpath", l_get_worldpath},
1155 {"sound_play", l_sound_play},
1156 {"sound_stop", l_sound_stop},
1157 {"is_singleplayer", l_is_singleplayer},
1158 {"get_password_hash", l_get_password_hash},
1159 {"notify_authentication_modified", l_notify_authentication_modified},
1160 {"get_craft_result", l_get_craft_result},
1161 {"get_craft_recipe", l_get_craft_recipe},
1162 {"get_all_craft_recipes", l_get_all_craft_recipes},
1163 {"rollback_get_last_node_actor", l_rollback_get_last_node_actor},
1164 {"rollback_revert_actions_by", l_rollback_revert_actions_by},
1170 Main export function
1173 void scriptapi_export(lua_State *L, Server *server)
1176 assert(lua_checkstack(L, 20));
1177 verbosestream<<"scriptapi_export()"<<std::endl;
1178 StackUnroller stack_unroller(L);
1180 // Store server as light userdata in registry
1181 lua_pushlightuserdata(L, server);
1182 lua_setfield(L, LUA_REGISTRYINDEX, "minetest_server");
1184 // Register global functions in table minetest
1186 luaL_register(L, NULL, minetest_f);
1187 lua_setglobal(L, "minetest");
1189 // Get the main minetest table
1190 lua_getglobal(L, "minetest");
1192 // Add tables to minetest
1194 lua_setfield(L, -2, "object_refs");
1196 lua_setfield(L, -2, "luaentities");
1198 // Register wrappers
1199 LuaItemStack::Register(L);
1200 InvRef::Register(L);
1201 NodeMetaRef::Register(L);
1202 NodeTimerRef::Register(L);
1203 ObjectRef::Register(L);
1204 EnvRef::Register(L);
1205 LuaPseudoRandom::Register(L);
1206 LuaPerlinNoise::Register(L);
1207 LuaPerlinNoiseMap::Register(L);