l_server.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "lua_api/l_server.h"
  17. #include "lua_api/l_internal.h"
  18. #include "common/c_converter.h"
  19. #include "common/c_content.h"
  20. #include "common/c_packer.h"
  21. #include "cpp_api/s_base.h"
  22. #include "cpp_api/s_security.h"
  23. #include "scripting_server.h"
  24. #include "server.h"
  25. #include "environment.h"
  26. #include "remoteplayer.h"
  27. #include "log.h"
  28. #include <algorithm>
  29. // request_shutdown()
  30. int ModApiServer::l_request_shutdown(lua_State *L)
  31. {
  32. NO_MAP_LOCK_REQUIRED;
  33. const char *msg = lua_tolstring(L, 1, NULL);
  34. bool reconnect = readParam<bool>(L, 2);
  35. float seconds_before_shutdown = lua_tonumber(L, 3);
  36. getServer(L)->requestShutdown(msg ? msg : "", reconnect, seconds_before_shutdown);
  37. return 0;
  38. }
  39. // get_server_status()
  40. int ModApiServer::l_get_server_status(lua_State *L)
  41. {
  42. NO_MAP_LOCK_REQUIRED;
  43. lua_pushstring(L, getServer(L)->getStatusString().c_str());
  44. return 1;
  45. }
  46. // get_server_uptime()
  47. int ModApiServer::l_get_server_uptime(lua_State *L)
  48. {
  49. NO_MAP_LOCK_REQUIRED;
  50. lua_pushnumber(L, getServer(L)->getUptime());
  51. return 1;
  52. }
  53. // get_server_max_lag()
  54. int ModApiServer::l_get_server_max_lag(lua_State *L)
  55. {
  56. NO_MAP_LOCK_REQUIRED;
  57. GET_ENV_PTR;
  58. lua_pushnumber(L, env->getMaxLagEstimate());
  59. return 1;
  60. }
  61. // print(text)
  62. int ModApiServer::l_print(lua_State *L)
  63. {
  64. NO_MAP_LOCK_REQUIRED;
  65. std::string text;
  66. text = luaL_checkstring(L, 1);
  67. getServer(L)->printToConsoleOnly(text);
  68. return 0;
  69. }
  70. // chat_send_all(text)
  71. int ModApiServer::l_chat_send_all(lua_State *L)
  72. {
  73. NO_MAP_LOCK_REQUIRED;
  74. const char *text = luaL_checkstring(L, 1);
  75. // Get server from registry
  76. Server *server = getServer(L);
  77. // Send
  78. try {
  79. server->notifyPlayers(utf8_to_wide(text));
  80. } catch (PacketError &e) {
  81. warningstream << "Exception caught: " << e.what() << std::endl
  82. << script_get_backtrace(L) << std::endl;
  83. server->notifyPlayers(utf8_to_wide(std::string("Internal error: ") + e.what()));
  84. }
  85. return 0;
  86. }
  87. // chat_send_player(name, text)
  88. int ModApiServer::l_chat_send_player(lua_State *L)
  89. {
  90. NO_MAP_LOCK_REQUIRED;
  91. const char *name = luaL_checkstring(L, 1);
  92. const char *text = luaL_checkstring(L, 2);
  93. // Get server from registry
  94. Server *server = getServer(L);
  95. // Send
  96. try {
  97. server->notifyPlayer(name, utf8_to_wide(text));
  98. } catch (PacketError &e) {
  99. warningstream << "Exception caught: " << e.what() << std::endl
  100. << script_get_backtrace(L) << std::endl;
  101. server->notifyPlayer(name, utf8_to_wide(std::string("Internal error: ") + e.what()));
  102. }
  103. return 0;
  104. }
  105. // get_player_privs(name, text)
  106. int ModApiServer::l_get_player_privs(lua_State *L)
  107. {
  108. NO_MAP_LOCK_REQUIRED;
  109. const char *name = luaL_checkstring(L, 1);
  110. // Get server from registry
  111. Server *server = getServer(L);
  112. // Do it
  113. lua_newtable(L);
  114. int table = lua_gettop(L);
  115. std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
  116. for (const std::string &privs_ : privs_s) {
  117. lua_pushboolean(L, true);
  118. lua_setfield(L, table, privs_.c_str());
  119. }
  120. lua_pushvalue(L, table);
  121. return 1;
  122. }
  123. // get_player_ip()
  124. int ModApiServer::l_get_player_ip(lua_State *L)
  125. {
  126. NO_MAP_LOCK_REQUIRED;
  127. Server *server = getServer(L);
  128. const char *name = luaL_checkstring(L, 1);
  129. RemotePlayer *player = server->getEnv().getPlayer(name);
  130. if (!player) {
  131. lua_pushnil(L); // no such player
  132. return 1;
  133. }
  134. lua_pushstring(L, server->getPeerAddress(player->getPeerId()).serializeString().c_str());
  135. return 1;
  136. }
  137. // get_player_information(name)
  138. int ModApiServer::l_get_player_information(lua_State *L)
  139. {
  140. NO_MAP_LOCK_REQUIRED;
  141. Server *server = getServer(L);
  142. const char *name = luaL_checkstring(L, 1);
  143. RemotePlayer *player = server->getEnv().getPlayer(name);
  144. if (!player) {
  145. lua_pushnil(L); // no such player
  146. return 1;
  147. }
  148. /*
  149. Be careful not to introduce a depdendency on the connection to
  150. the peer here. This function is >>REQUIRED<< to still be able to return
  151. values even when the peer unexpectedly disappears.
  152. Hence all the ConInfo values here are optional.
  153. */
  154. auto getConInfo = [&] (con::rtt_stat_type type, float *value) -> bool {
  155. return server->getClientConInfo(player->getPeerId(), type, value);
  156. };
  157. float min_rtt, max_rtt, avg_rtt, min_jitter, max_jitter, avg_jitter;
  158. bool have_con_info =
  159. getConInfo(con::MIN_RTT, &min_rtt) &&
  160. getConInfo(con::MAX_RTT, &max_rtt) &&
  161. getConInfo(con::AVG_RTT, &avg_rtt) &&
  162. getConInfo(con::MIN_JITTER, &min_jitter) &&
  163. getConInfo(con::MAX_JITTER, &max_jitter) &&
  164. getConInfo(con::AVG_JITTER, &avg_jitter);
  165. ClientInfo info;
  166. if (!server->getClientInfo(player->getPeerId(), info)) {
  167. warningstream << FUNCTION_NAME << ": no client info?!" << std::endl;
  168. lua_pushnil(L); // error
  169. return 1;
  170. }
  171. lua_newtable(L);
  172. int table = lua_gettop(L);
  173. lua_pushstring(L,"address");
  174. lua_pushstring(L, info.addr.serializeString().c_str());
  175. lua_settable(L, table);
  176. lua_pushstring(L,"ip_version");
  177. if (info.addr.getFamily() == AF_INET) {
  178. lua_pushnumber(L, 4);
  179. } else if (info.addr.getFamily() == AF_INET6) {
  180. lua_pushnumber(L, 6);
  181. } else {
  182. lua_pushnumber(L, 0);
  183. }
  184. lua_settable(L, table);
  185. if (have_con_info) { // may be missing
  186. lua_pushstring(L, "min_rtt");
  187. lua_pushnumber(L, min_rtt);
  188. lua_settable(L, table);
  189. lua_pushstring(L, "max_rtt");
  190. lua_pushnumber(L, max_rtt);
  191. lua_settable(L, table);
  192. lua_pushstring(L, "avg_rtt");
  193. lua_pushnumber(L, avg_rtt);
  194. lua_settable(L, table);
  195. lua_pushstring(L, "min_jitter");
  196. lua_pushnumber(L, min_jitter);
  197. lua_settable(L, table);
  198. lua_pushstring(L, "max_jitter");
  199. lua_pushnumber(L, max_jitter);
  200. lua_settable(L, table);
  201. lua_pushstring(L, "avg_jitter");
  202. lua_pushnumber(L, avg_jitter);
  203. lua_settable(L, table);
  204. }
  205. lua_pushstring(L,"connection_uptime");
  206. lua_pushnumber(L, info.uptime);
  207. lua_settable(L, table);
  208. lua_pushstring(L,"protocol_version");
  209. lua_pushnumber(L, info.prot_vers);
  210. lua_settable(L, table);
  211. lua_pushstring(L, "formspec_version");
  212. lua_pushnumber(L, player->formspec_version);
  213. lua_settable(L, table);
  214. lua_pushstring(L, "lang_code");
  215. lua_pushstring(L, info.lang_code.c_str());
  216. lua_settable(L, table);
  217. #ifndef NDEBUG
  218. lua_pushstring(L,"serialization_version");
  219. lua_pushnumber(L, info.ser_vers);
  220. lua_settable(L, table);
  221. lua_pushstring(L,"major");
  222. lua_pushnumber(L, info.major);
  223. lua_settable(L, table);
  224. lua_pushstring(L,"minor");
  225. lua_pushnumber(L, info.minor);
  226. lua_settable(L, table);
  227. lua_pushstring(L,"patch");
  228. lua_pushnumber(L, info.patch);
  229. lua_settable(L, table);
  230. lua_pushstring(L,"version_string");
  231. lua_pushstring(L, info.vers_string.c_str());
  232. lua_settable(L, table);
  233. lua_pushstring(L,"state");
  234. lua_pushstring(L, ClientInterface::state2Name(info.state).c_str());
  235. lua_settable(L, table);
  236. #endif
  237. return 1;
  238. }
  239. // get_player_window_information(name)
  240. int ModApiServer::l_get_player_window_information(lua_State *L)
  241. {
  242. NO_MAP_LOCK_REQUIRED;
  243. Server *server = getServer(L);
  244. const char *name = luaL_checkstring(L, 1);
  245. RemotePlayer *player = server->getEnv().getPlayer(name);
  246. if (!player)
  247. return 0;
  248. auto dynamic = server->getClientDynamicInfo(player->getPeerId());
  249. if (!dynamic || dynamic->render_target_size == v2u32())
  250. return 0;
  251. lua_newtable(L);
  252. int dyn_table = lua_gettop(L);
  253. lua_pushstring(L, "size");
  254. push_v2u32(L, dynamic->render_target_size);
  255. lua_settable(L, dyn_table);
  256. lua_pushstring(L, "max_formspec_size");
  257. push_v2f(L, dynamic->max_fs_size);
  258. lua_settable(L, dyn_table);
  259. lua_pushstring(L, "real_gui_scaling");
  260. lua_pushnumber(L, dynamic->real_gui_scaling);
  261. lua_settable(L, dyn_table);
  262. lua_pushstring(L, "real_hud_scaling");
  263. lua_pushnumber(L, dynamic->real_hud_scaling);
  264. lua_settable(L, dyn_table);
  265. return 1;
  266. }
  267. // get_ban_list()
  268. int ModApiServer::l_get_ban_list(lua_State *L)
  269. {
  270. NO_MAP_LOCK_REQUIRED;
  271. lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
  272. return 1;
  273. }
  274. // get_ban_description()
  275. int ModApiServer::l_get_ban_description(lua_State *L)
  276. {
  277. NO_MAP_LOCK_REQUIRED;
  278. const char * ip_or_name = luaL_checkstring(L, 1);
  279. lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
  280. return 1;
  281. }
  282. // ban_player()
  283. int ModApiServer::l_ban_player(lua_State *L)
  284. {
  285. NO_MAP_LOCK_REQUIRED;
  286. if (!getEnv(L))
  287. throw LuaError("Can't ban player before server has started up");
  288. Server *server = getServer(L);
  289. const char *name = luaL_checkstring(L, 1);
  290. RemotePlayer *player = server->getEnv().getPlayer(name);
  291. if (!player) {
  292. lua_pushboolean(L, false); // no such player
  293. return 1;
  294. }
  295. std::string ip_str = server->getPeerAddress(player->getPeerId()).serializeString();
  296. server->setIpBanned(ip_str, name);
  297. lua_pushboolean(L, true);
  298. return 1;
  299. }
  300. // disconnect_player(name, [reason]) -> success
  301. int ModApiServer::l_disconnect_player(lua_State *L)
  302. {
  303. NO_MAP_LOCK_REQUIRED;
  304. if (!getEnv(L))
  305. throw LuaError("Can't kick player before server has started up");
  306. const char *name = luaL_checkstring(L, 1);
  307. std::string message;
  308. if (lua_isstring(L, 2))
  309. message.append(readParam<std::string>(L, 2));
  310. else
  311. message.append("Disconnected.");
  312. Server *server = getServer(L);
  313. RemotePlayer *player = server->getEnv().getPlayer(name);
  314. if (!player) {
  315. lua_pushboolean(L, false); // No such player
  316. return 1;
  317. }
  318. server->DenyAccess(player->getPeerId(), SERVER_ACCESSDENIED_CUSTOM_STRING, message);
  319. lua_pushboolean(L, true);
  320. return 1;
  321. }
  322. int ModApiServer::l_remove_player(lua_State *L)
  323. {
  324. NO_MAP_LOCK_REQUIRED;
  325. std::string name = luaL_checkstring(L, 1);
  326. ServerEnvironment *s_env = dynamic_cast<ServerEnvironment *>(getEnv(L));
  327. if (!s_env)
  328. throw LuaError("Can't remove player before server has started up");
  329. RemotePlayer *player = s_env->getPlayer(name.c_str());
  330. if (!player)
  331. lua_pushinteger(L, s_env->removePlayerFromDatabase(name) ? 0 : 1);
  332. else
  333. lua_pushinteger(L, 2);
  334. return 1;
  335. }
  336. // unban_player_or_ip()
  337. int ModApiServer::l_unban_player_or_ip(lua_State *L)
  338. {
  339. NO_MAP_LOCK_REQUIRED;
  340. const char * ip_or_name = luaL_checkstring(L, 1);
  341. getServer(L)->unsetIpBanned(ip_or_name);
  342. lua_pushboolean(L, true);
  343. return 1;
  344. }
  345. // show_formspec(playername,formname,formspec)
  346. int ModApiServer::l_show_formspec(lua_State *L)
  347. {
  348. NO_MAP_LOCK_REQUIRED;
  349. const char *playername = luaL_checkstring(L, 1);
  350. const char *formname = luaL_checkstring(L, 2);
  351. const char *formspec = luaL_checkstring(L, 3);
  352. if(getServer(L)->showFormspec(playername,formspec,formname))
  353. {
  354. lua_pushboolean(L, true);
  355. }else{
  356. lua_pushboolean(L, false);
  357. }
  358. return 1;
  359. }
  360. // get_current_modname()
  361. int ModApiServer::l_get_current_modname(lua_State *L)
  362. {
  363. NO_MAP_LOCK_REQUIRED;
  364. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
  365. return 1;
  366. }
  367. // get_modpath(modname)
  368. int ModApiServer::l_get_modpath(lua_State *L)
  369. {
  370. NO_MAP_LOCK_REQUIRED;
  371. std::string modname = luaL_checkstring(L, 1);
  372. const ModSpec *mod = getGameDef(L)->getModSpec(modname);
  373. if (!mod)
  374. lua_pushnil(L);
  375. else
  376. lua_pushstring(L, mod->path.c_str());
  377. return 1;
  378. }
  379. // get_modnames()
  380. // the returned list is sorted alphabetically for you
  381. int ModApiServer::l_get_modnames(lua_State *L)
  382. {
  383. NO_MAP_LOCK_REQUIRED;
  384. // Get a list of mods
  385. std::vector<std::string> modlist;
  386. for (auto &it : getGameDef(L)->getMods())
  387. modlist.emplace_back(it.name);
  388. std::sort(modlist.begin(), modlist.end());
  389. // Package them up for Lua
  390. lua_createtable(L, modlist.size(), 0);
  391. auto iter = modlist.begin();
  392. for (u16 i = 0; iter != modlist.end(); ++iter) {
  393. lua_pushstring(L, iter->c_str());
  394. lua_rawseti(L, -2, ++i);
  395. }
  396. return 1;
  397. }
  398. // get_game_info()
  399. int ModApiServer::l_get_game_info(lua_State *L)
  400. {
  401. NO_MAP_LOCK_REQUIRED;
  402. const SubgameSpec *game_spec = getGameDef(L)->getGameSpec();
  403. assert(game_spec);
  404. lua_newtable(L);
  405. setstringfield(L, -1, "id", game_spec->id);
  406. setstringfield(L, -1, "title", game_spec->title);
  407. setstringfield(L, -1, "author", game_spec->author);
  408. setstringfield(L, -1, "path", game_spec->path);
  409. return 1;
  410. }
  411. // get_worldpath()
  412. int ModApiServer::l_get_worldpath(lua_State *L)
  413. {
  414. NO_MAP_LOCK_REQUIRED;
  415. const Server *srv = getServer(L);
  416. lua_pushstring(L, srv->getWorldPath().c_str());
  417. return 1;
  418. }
  419. // sound_play(spec, parameters, [ephemeral])
  420. int ModApiServer::l_sound_play(lua_State *L)
  421. {
  422. NO_MAP_LOCK_REQUIRED;
  423. ServerPlayingSound params;
  424. read_simplesoundspec(L, 1, params.spec);
  425. read_server_sound_params(L, 2, params);
  426. bool ephemeral = lua_gettop(L) > 2 && readParam<bool>(L, 3);
  427. if (ephemeral) {
  428. getServer(L)->playSound(params, true);
  429. lua_pushnil(L);
  430. } else {
  431. s32 handle = getServer(L)->playSound(params);
  432. lua_pushinteger(L, handle);
  433. }
  434. return 1;
  435. }
  436. // sound_stop(handle)
  437. int ModApiServer::l_sound_stop(lua_State *L)
  438. {
  439. NO_MAP_LOCK_REQUIRED;
  440. s32 handle = luaL_checkinteger(L, 1);
  441. getServer(L)->stopSound(handle);
  442. return 0;
  443. }
  444. int ModApiServer::l_sound_fade(lua_State *L)
  445. {
  446. NO_MAP_LOCK_REQUIRED;
  447. s32 handle = luaL_checkinteger(L, 1);
  448. float step = readParam<float>(L, 2);
  449. float gain = readParam<float>(L, 3);
  450. getServer(L)->fadeSound(handle, step, gain);
  451. return 0;
  452. }
  453. // dynamic_add_media(filepath)
  454. int ModApiServer::l_dynamic_add_media(lua_State *L)
  455. {
  456. NO_MAP_LOCK_REQUIRED;
  457. if (!getEnv(L))
  458. throw LuaError("Dynamic media cannot be added before server has started up");
  459. Server *server = getServer(L);
  460. std::string filepath;
  461. std::string to_player;
  462. bool ephemeral = false;
  463. if (lua_istable(L, 1)) {
  464. getstringfield(L, 1, "filepath", filepath);
  465. getstringfield(L, 1, "to_player", to_player);
  466. getboolfield(L, 1, "ephemeral", ephemeral);
  467. } else {
  468. filepath = readParam<std::string>(L, 1);
  469. }
  470. if (filepath.empty())
  471. luaL_typerror(L, 1, "non-empty string");
  472. luaL_checktype(L, 2, LUA_TFUNCTION);
  473. CHECK_SECURE_PATH(L, filepath.c_str(), false);
  474. u32 token = server->getScriptIface()->allocateDynamicMediaCallback(L, 2);
  475. bool ok = server->dynamicAddMedia(filepath, token, to_player, ephemeral);
  476. if (!ok)
  477. server->getScriptIface()->freeDynamicMediaCallback(token);
  478. lua_pushboolean(L, ok);
  479. return 1;
  480. }
  481. // is_singleplayer()
  482. int ModApiServer::l_is_singleplayer(lua_State *L)
  483. {
  484. NO_MAP_LOCK_REQUIRED;
  485. const Server *srv = getServer(L);
  486. lua_pushboolean(L, srv->isSingleplayer());
  487. return 1;
  488. }
  489. // notify_authentication_modified(name)
  490. int ModApiServer::l_notify_authentication_modified(lua_State *L)
  491. {
  492. NO_MAP_LOCK_REQUIRED;
  493. std::string name;
  494. if(lua_isstring(L, 1))
  495. name = readParam<std::string>(L, 1);
  496. getServer(L)->reportPrivsModified(name);
  497. return 0;
  498. }
  499. // do_async_callback(func, params, mod_origin)
  500. int ModApiServer::l_do_async_callback(lua_State *L)
  501. {
  502. NO_MAP_LOCK_REQUIRED;
  503. ServerScripting *script = getScriptApi<ServerScripting>(L);
  504. luaL_checktype(L, 1, LUA_TFUNCTION);
  505. luaL_checktype(L, 2, LUA_TTABLE);
  506. luaL_checktype(L, 3, LUA_TSTRING);
  507. call_string_dump(L, 1);
  508. size_t func_length;
  509. const char *serialized_func_raw = lua_tolstring(L, -1, &func_length);
  510. PackedValue *param = script_pack(L, 2);
  511. std::string mod_origin = readParam<std::string>(L, 3);
  512. u32 jobId = script->queueAsync(
  513. std::string(serialized_func_raw, func_length),
  514. param, mod_origin);
  515. lua_settop(L, 0);
  516. lua_pushinteger(L, jobId);
  517. return 1;
  518. }
  519. // register_async_dofile(path)
  520. int ModApiServer::l_register_async_dofile(lua_State *L)
  521. {
  522. NO_MAP_LOCK_REQUIRED;
  523. std::string path = readParam<std::string>(L, 1);
  524. CHECK_SECURE_PATH(L, path.c_str(), false);
  525. // Find currently running mod name (only at init time)
  526. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
  527. if (!lua_isstring(L, -1))
  528. return 0;
  529. std::string modname = readParam<std::string>(L, -1);
  530. getServer(L)->m_async_init_files.emplace_back(modname, path);
  531. lua_pushboolean(L, true);
  532. return 1;
  533. }
  534. // serialize_roundtrip(value)
  535. // Meant for unit testing the packer from Lua
  536. int ModApiServer::l_serialize_roundtrip(lua_State *L)
  537. {
  538. NO_MAP_LOCK_REQUIRED;
  539. int top = lua_gettop(L);
  540. auto *pv = script_pack(L, 1);
  541. if (top != lua_gettop(L))
  542. throw LuaError("stack values leaked");
  543. #ifndef NDEBUG
  544. script_dump_packed(pv);
  545. #endif
  546. top = lua_gettop(L);
  547. script_unpack(L, pv);
  548. delete pv;
  549. if (top + 1 != lua_gettop(L))
  550. throw LuaError("stack values leaked");
  551. return 1;
  552. }
  553. void ModApiServer::Initialize(lua_State *L, int top)
  554. {
  555. API_FCT(request_shutdown);
  556. API_FCT(get_server_status);
  557. API_FCT(get_server_uptime);
  558. API_FCT(get_server_max_lag);
  559. API_FCT(get_worldpath);
  560. API_FCT(is_singleplayer);
  561. API_FCT(get_current_modname);
  562. API_FCT(get_modpath);
  563. API_FCT(get_modnames);
  564. API_FCT(get_game_info);
  565. API_FCT(print);
  566. API_FCT(chat_send_all);
  567. API_FCT(chat_send_player);
  568. API_FCT(show_formspec);
  569. API_FCT(sound_play);
  570. API_FCT(sound_stop);
  571. API_FCT(sound_fade);
  572. API_FCT(dynamic_add_media);
  573. API_FCT(get_player_information);
  574. API_FCT(get_player_window_information);
  575. API_FCT(get_player_privs);
  576. API_FCT(get_player_ip);
  577. API_FCT(get_ban_list);
  578. API_FCT(get_ban_description);
  579. API_FCT(ban_player);
  580. API_FCT(disconnect_player);
  581. API_FCT(remove_player);
  582. API_FCT(unban_player_or_ip);
  583. API_FCT(notify_authentication_modified);
  584. API_FCT(do_async_callback);
  585. API_FCT(register_async_dofile);
  586. API_FCT(serialize_roundtrip);
  587. }
  588. void ModApiServer::InitializeAsync(lua_State *L, int top)
  589. {
  590. API_FCT(get_worldpath);
  591. API_FCT(is_singleplayer);
  592. API_FCT(get_current_modname);
  593. API_FCT(get_modpath);
  594. API_FCT(get_modnames);
  595. API_FCT(get_game_info);
  596. }