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 "lua_api/l_server.h"
21 #include "lua_api/l_internal.h"
22 #include "common/c_converter.h"
23 #include "common/c_content.h"
24 #include "cpp_api/s_base.h"
26 #include "environment.h"
31 int ModApiServer::l_request_shutdown(lua_State *L)
34 const char *msg = lua_tolstring(L, 1, NULL);
35 bool reconnect = lua_toboolean(L, 2);
36 getServer(L)->requestShutdown(msg ? msg : "", reconnect);
40 // get_server_status()
41 int ModApiServer::l_get_server_status(lua_State *L)
44 lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
49 int ModApiServer::l_print(lua_State *L)
53 text = luaL_checkstring(L, 1);
54 getServer(L)->printToConsoleOnly(text);
58 // chat_send_all(text)
59 int ModApiServer::l_chat_send_all(lua_State *L)
62 const char *text = luaL_checkstring(L, 1);
63 // Get server from registry
64 Server *server = getServer(L);
66 server->notifyPlayers(narrow_to_wide(text));
70 // chat_send_player(name, text)
71 int ModApiServer::l_chat_send_player(lua_State *L)
74 const char *name = luaL_checkstring(L, 1);
75 const char *text = luaL_checkstring(L, 2);
77 // Get server from registry
78 Server *server = getServer(L);
80 server->notifyPlayer(name, narrow_to_wide(text));
84 // get_player_privs(name, text)
85 int ModApiServer::l_get_player_privs(lua_State *L)
88 const char *name = luaL_checkstring(L, 1);
89 // Get server from registry
90 Server *server = getServer(L);
93 int table = lua_gettop(L);
94 std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
95 for(std::set<std::string>::const_iterator
96 i = privs_s.begin(); i != privs_s.end(); i++){
97 lua_pushboolean(L, true);
98 lua_setfield(L, table, i->c_str());
100 lua_pushvalue(L, table);
105 int ModApiServer::l_get_player_ip(lua_State *L)
107 NO_MAP_LOCK_REQUIRED;
108 const char * name = luaL_checkstring(L, 1);
109 Player *player = getEnv(L)->getPlayer(name);
112 lua_pushnil(L); // no such player
117 Address addr = getServer(L)->getPeerAddress(player->peer_id);
118 std::string ip_str = addr.serializeString();
119 lua_pushstring(L, ip_str.c_str());
122 catch(con::PeerNotFoundException) // unlikely
124 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
125 lua_pushnil(L); // error
130 // get_player_information()
131 int ModApiServer::l_get_player_information(lua_State *L)
134 NO_MAP_LOCK_REQUIRED;
135 const char * name = luaL_checkstring(L, 1);
136 Player *player = getEnv(L)->getPlayer(name);
139 lua_pushnil(L); // no such player
146 addr = getServer(L)->getPeerAddress(player->peer_id);
148 catch(con::PeerNotFoundException) // unlikely
150 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
151 lua_pushnil(L); // error
155 float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
159 u8 ser_vers,major,minor,patch;
160 std::string vers_string;
164 dstream << FUNCTION_NAME << ": peer was not found" << std::endl; \
165 lua_pushnil(L); /* error */ \
169 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_RTT,&min_rtt))
170 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_RTT,&max_rtt))
171 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_RTT,&avg_rtt))
172 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_JITTER,&min_jitter))
173 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_JITTER,&max_jitter))
174 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_JITTER,&avg_jitter))
176 ERET(getServer(L)->getClientInfo(player->peer_id,
177 &state, &uptime, &ser_vers, &prot_vers,
178 &major, &minor, &patch, &vers_string))
181 int table = lua_gettop(L);
183 lua_pushstring(L,"address");
184 lua_pushstring(L, addr.serializeString().c_str());
185 lua_settable(L, table);
187 lua_pushstring(L,"ip_version");
188 if (addr.getFamily() == AF_INET) {
189 lua_pushnumber(L, 4);
190 } else if (addr.getFamily() == AF_INET6) {
191 lua_pushnumber(L, 6);
193 lua_pushnumber(L, 0);
195 lua_settable(L, table);
197 lua_pushstring(L,"min_rtt");
198 lua_pushnumber(L, min_rtt);
199 lua_settable(L, table);
201 lua_pushstring(L,"max_rtt");
202 lua_pushnumber(L, max_rtt);
203 lua_settable(L, table);
205 lua_pushstring(L,"avg_rtt");
206 lua_pushnumber(L, avg_rtt);
207 lua_settable(L, table);
209 lua_pushstring(L,"min_jitter");
210 lua_pushnumber(L, min_jitter);
211 lua_settable(L, table);
213 lua_pushstring(L,"max_jitter");
214 lua_pushnumber(L, max_jitter);
215 lua_settable(L, table);
217 lua_pushstring(L,"avg_jitter");
218 lua_pushnumber(L, avg_jitter);
219 lua_settable(L, table);
221 lua_pushstring(L,"connection_uptime");
222 lua_pushnumber(L, uptime);
223 lua_settable(L, table);
226 lua_pushstring(L,"serialization_version");
227 lua_pushnumber(L, ser_vers);
228 lua_settable(L, table);
230 lua_pushstring(L,"protocol_version");
231 lua_pushnumber(L, prot_vers);
232 lua_settable(L, table);
234 lua_pushstring(L,"major");
235 lua_pushnumber(L, major);
236 lua_settable(L, table);
238 lua_pushstring(L,"minor");
239 lua_pushnumber(L, minor);
240 lua_settable(L, table);
242 lua_pushstring(L,"patch");
243 lua_pushnumber(L, patch);
244 lua_settable(L, table);
246 lua_pushstring(L,"version_string");
247 lua_pushstring(L, vers_string.c_str());
248 lua_settable(L, table);
250 lua_pushstring(L,"state");
251 lua_pushstring(L,ClientInterface::state2Name(state).c_str());
252 lua_settable(L, table);
260 int ModApiServer::l_get_ban_list(lua_State *L)
262 NO_MAP_LOCK_REQUIRED;
263 lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
267 // get_ban_description()
268 int ModApiServer::l_get_ban_description(lua_State *L)
270 NO_MAP_LOCK_REQUIRED;
271 const char * ip_or_name = luaL_checkstring(L, 1);
272 lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
277 int ModApiServer::l_ban_player(lua_State *L)
279 NO_MAP_LOCK_REQUIRED;
280 const char * name = luaL_checkstring(L, 1);
281 Player *player = getEnv(L)->getPlayer(name);
284 lua_pushboolean(L, false); // no such player
289 Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
290 std::string ip_str = addr.serializeString();
291 getServer(L)->setIpBanned(ip_str, name);
293 catch(con::PeerNotFoundException) // unlikely
295 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
296 lua_pushboolean(L, false); // error
299 lua_pushboolean(L, true);
303 // kick_player(name, [reason]) -> success
304 int ModApiServer::l_kick_player(lua_State *L)
306 NO_MAP_LOCK_REQUIRED;
307 const char *name = luaL_checkstring(L, 1);
309 if (lua_isstring(L, 2))
311 message = std::string("Kicked: ") + lua_tostring(L, 2);
317 Player *player = getEnv(L)->getPlayer(name);
320 lua_pushboolean(L, false); // No such player
323 getServer(L)->DenyAccess_Legacy(player->peer_id, utf8_to_wide(message));
324 lua_pushboolean(L, true);
328 // unban_player_or_ip()
329 int ModApiServer::l_unban_player_or_ip(lua_State *L)
331 NO_MAP_LOCK_REQUIRED;
332 const char * ip_or_name = luaL_checkstring(L, 1);
333 getServer(L)->unsetIpBanned(ip_or_name);
334 lua_pushboolean(L, true);
338 // show_formspec(playername,formname,formspec)
339 int ModApiServer::l_show_formspec(lua_State *L)
341 NO_MAP_LOCK_REQUIRED;
342 const char *playername = luaL_checkstring(L, 1);
343 const char *formname = luaL_checkstring(L, 2);
344 const char *formspec = luaL_checkstring(L, 3);
346 if(getServer(L)->showFormspec(playername,formspec,formname))
348 lua_pushboolean(L, true);
350 lua_pushboolean(L, false);
355 // get_current_modname()
356 int ModApiServer::l_get_current_modname(lua_State *L)
358 NO_MAP_LOCK_REQUIRED;
359 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
363 // get_modpath(modname)
364 int ModApiServer::l_get_modpath(lua_State *L)
366 NO_MAP_LOCK_REQUIRED;
367 std::string modname = luaL_checkstring(L, 1);
368 const ModSpec *mod = getServer(L)->getModSpec(modname);
373 lua_pushstring(L, mod->path.c_str());
378 // the returned list is sorted alphabetically for you
379 int ModApiServer::l_get_modnames(lua_State *L)
381 NO_MAP_LOCK_REQUIRED;
383 // Get a list of mods
384 std::vector<std::string> modlist;
385 getServer(L)->getModNames(modlist);
387 // Take unsorted items from mods_unsorted and sort them into
388 // mods_sorted; not great performance but the number of mods on a
389 // server will likely be small.
390 std::sort(modlist.begin(), modlist.end());
392 // Package them up for Lua
393 lua_createtable(L, modlist.size(), 0);
394 std::vector<std::string>::iterator iter = modlist.begin();
395 for (u16 i = 0; iter != modlist.end(); iter++) {
396 lua_pushstring(L, iter->c_str());
397 lua_rawseti(L, -2, ++i);
403 int ModApiServer::l_get_worldpath(lua_State *L)
405 NO_MAP_LOCK_REQUIRED;
406 std::string worldpath = getServer(L)->getWorldPath();
407 lua_pushstring(L, worldpath.c_str());
411 // sound_play(spec, parameters)
412 int ModApiServer::l_sound_play(lua_State *L)
414 NO_MAP_LOCK_REQUIRED;
415 SimpleSoundSpec spec;
416 read_soundspec(L, 1, spec);
417 ServerSoundParams params;
418 read_server_sound_params(L, 2, params);
419 s32 handle = getServer(L)->playSound(spec, params);
420 lua_pushinteger(L, handle);
424 // sound_stop(handle)
425 int ModApiServer::l_sound_stop(lua_State *L)
427 NO_MAP_LOCK_REQUIRED;
428 int handle = luaL_checkinteger(L, 1);
429 getServer(L)->stopSound(handle);
434 int ModApiServer::l_is_singleplayer(lua_State *L)
436 NO_MAP_LOCK_REQUIRED;
437 lua_pushboolean(L, getServer(L)->isSingleplayer());
441 // notify_authentication_modified(name)
442 int ModApiServer::l_notify_authentication_modified(lua_State *L)
444 NO_MAP_LOCK_REQUIRED;
445 std::string name = "";
446 if(lua_isstring(L, 1))
447 name = lua_tostring(L, 1);
448 getServer(L)->reportPrivsModified(name);
452 // get_last_run_mod()
453 int ModApiServer::l_get_last_run_mod(lua_State *L)
455 NO_MAP_LOCK_REQUIRED;
456 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
457 const char *current_mod = lua_tostring(L, -1);
458 if (current_mod == NULL || current_mod[0] == '\0') {
460 lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
465 // set_last_run_mod(modname)
466 int ModApiServer::l_set_last_run_mod(lua_State *L)
468 NO_MAP_LOCK_REQUIRED;
469 #ifdef SCRIPTAPI_DEBUG
470 const char *mod = lua_tostring(L, 1);
471 getScriptApiBase(L)->setOriginDirect(mod);
472 //printf(">>>> last mod set from Lua: %s\n", mod);
478 // cause_error(type_of_error)
479 int ModApiServer::l_cause_error(lua_State *L)
481 NO_MAP_LOCK_REQUIRED;
482 std::string type_of_error = "none";
483 if(lua_isstring(L, 1))
484 type_of_error = lua_tostring(L, 1);
486 errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
488 if(type_of_error == "segv") {
489 volatile int* some_pointer = 0;
490 errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
492 } else if (type_of_error == "zerodivision") {
494 unsigned int some_number = porting::getTimeS();
495 unsigned int zerovalue = 0;
496 unsigned int result = some_number / zerovalue;
497 errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
499 } else if (type_of_error == "exception") {
500 throw BaseException("Errorhandler test fct called");
507 void ModApiServer::Initialize(lua_State *L, int top)
509 API_FCT(request_shutdown);
510 API_FCT(get_server_status);
511 API_FCT(get_worldpath);
512 API_FCT(is_singleplayer);
514 API_FCT(get_current_modname);
515 API_FCT(get_modpath);
516 API_FCT(get_modnames);
520 API_FCT(chat_send_all);
521 API_FCT(chat_send_player);
522 API_FCT(show_formspec);
526 API_FCT(get_player_information);
527 API_FCT(get_player_privs);
528 API_FCT(get_player_ip);
529 API_FCT(get_ban_list);
530 API_FCT(get_ban_description);
532 API_FCT(kick_player);
533 API_FCT(unban_player_or_ip);
534 API_FCT(notify_authentication_modified);
536 API_FCT(get_last_run_mod);
537 API_FCT(set_last_run_mod);
539 API_FCT(cause_error);