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)
33 const char *msg = lua_tolstring(L, 1, NULL);
34 bool reconnect = lua_toboolean(L, 2);
35 getServer(L)->requestShutdown(msg ? msg : "", reconnect);
39 // get_server_status()
40 int ModApiServer::l_get_server_status(lua_State *L)
43 lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
47 // chat_send_all(text)
48 int ModApiServer::l_chat_send_all(lua_State *L)
51 const char *text = luaL_checkstring(L, 1);
52 // Get server from registry
53 Server *server = getServer(L);
55 server->notifyPlayers(narrow_to_wide(text));
59 // chat_send_player(name, text)
60 int ModApiServer::l_chat_send_player(lua_State *L)
63 const char *name = luaL_checkstring(L, 1);
64 const char *text = luaL_checkstring(L, 2);
66 // Get server from registry
67 Server *server = getServer(L);
69 server->notifyPlayer(name, narrow_to_wide(text));
73 // get_player_privs(name, text)
74 int ModApiServer::l_get_player_privs(lua_State *L)
77 const char *name = luaL_checkstring(L, 1);
78 // Get server from registry
79 Server *server = getServer(L);
82 int table = lua_gettop(L);
83 std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
84 for(std::set<std::string>::const_iterator
85 i = privs_s.begin(); i != privs_s.end(); i++){
86 lua_pushboolean(L, true);
87 lua_setfield(L, table, i->c_str());
89 lua_pushvalue(L, table);
94 int ModApiServer::l_get_player_ip(lua_State *L)
97 const char * name = luaL_checkstring(L, 1);
98 Player *player = getEnv(L)->getPlayer(name);
101 lua_pushnil(L); // no such player
106 Address addr = getServer(L)->getPeerAddress(player->peer_id);
107 std::string ip_str = addr.serializeString();
108 lua_pushstring(L, ip_str.c_str());
111 catch(con::PeerNotFoundException) // unlikely
113 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
114 lua_pushnil(L); // error
119 // get_player_information()
120 int ModApiServer::l_get_player_information(lua_State *L)
123 NO_MAP_LOCK_REQUIRED;
124 const char * name = luaL_checkstring(L, 1);
125 Player *player = getEnv(L)->getPlayer(name);
128 lua_pushnil(L); // no such player
135 addr = getServer(L)->getPeerAddress(player->peer_id);
137 catch(con::PeerNotFoundException) // unlikely
139 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
140 lua_pushnil(L); // error
144 float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
148 u8 ser_vers,major,minor,patch;
149 std::string vers_string;
153 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; \
154 lua_pushnil(L); /* error */ \
158 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_RTT,&min_rtt))
159 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_RTT,&max_rtt))
160 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_RTT,&avg_rtt))
161 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_JITTER,&min_jitter))
162 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_JITTER,&max_jitter))
163 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_JITTER,&avg_jitter))
165 ERET(getServer(L)->getClientInfo(player->peer_id,
166 &state, &uptime, &ser_vers, &prot_vers,
167 &major, &minor, &patch, &vers_string))
170 int table = lua_gettop(L);
172 lua_pushstring(L,"address");
173 lua_pushstring(L, addr.serializeString().c_str());
174 lua_settable(L, table);
176 lua_pushstring(L,"ip_version");
177 if (addr.getFamily() == AF_INET) {
178 lua_pushnumber(L, 4);
179 } else if (addr.getFamily() == AF_INET6) {
180 lua_pushnumber(L, 6);
182 lua_pushnumber(L, 0);
184 lua_settable(L, table);
186 lua_pushstring(L,"min_rtt");
187 lua_pushnumber(L, min_rtt);
188 lua_settable(L, table);
190 lua_pushstring(L,"max_rtt");
191 lua_pushnumber(L, max_rtt);
192 lua_settable(L, table);
194 lua_pushstring(L,"avg_rtt");
195 lua_pushnumber(L, avg_rtt);
196 lua_settable(L, table);
198 lua_pushstring(L,"min_jitter");
199 lua_pushnumber(L, min_jitter);
200 lua_settable(L, table);
202 lua_pushstring(L,"max_jitter");
203 lua_pushnumber(L, max_jitter);
204 lua_settable(L, table);
206 lua_pushstring(L,"avg_jitter");
207 lua_pushnumber(L, avg_jitter);
208 lua_settable(L, table);
210 lua_pushstring(L,"connection_uptime");
211 lua_pushnumber(L, uptime);
212 lua_settable(L, table);
215 lua_pushstring(L,"serialization_version");
216 lua_pushnumber(L, ser_vers);
217 lua_settable(L, table);
219 lua_pushstring(L,"protocol_version");
220 lua_pushnumber(L, prot_vers);
221 lua_settable(L, table);
223 lua_pushstring(L,"major");
224 lua_pushnumber(L, major);
225 lua_settable(L, table);
227 lua_pushstring(L,"minor");
228 lua_pushnumber(L, minor);
229 lua_settable(L, table);
231 lua_pushstring(L,"patch");
232 lua_pushnumber(L, patch);
233 lua_settable(L, table);
235 lua_pushstring(L,"version_string");
236 lua_pushstring(L, vers_string.c_str());
237 lua_settable(L, table);
239 lua_pushstring(L,"state");
240 lua_pushstring(L,ClientInterface::state2Name(state).c_str());
241 lua_settable(L, table);
249 int ModApiServer::l_get_ban_list(lua_State *L)
251 NO_MAP_LOCK_REQUIRED;
252 lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
256 // get_ban_description()
257 int ModApiServer::l_get_ban_description(lua_State *L)
259 NO_MAP_LOCK_REQUIRED;
260 const char * ip_or_name = luaL_checkstring(L, 1);
261 lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
266 int ModApiServer::l_ban_player(lua_State *L)
268 NO_MAP_LOCK_REQUIRED;
269 const char * name = luaL_checkstring(L, 1);
270 Player *player = getEnv(L)->getPlayer(name);
273 lua_pushboolean(L, false); // no such player
278 Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
279 std::string ip_str = addr.serializeString();
280 getServer(L)->setIpBanned(ip_str, name);
282 catch(con::PeerNotFoundException) // unlikely
284 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
285 lua_pushboolean(L, false); // error
288 lua_pushboolean(L, true);
292 // kick_player(name, [reason]) -> success
293 int ModApiServer::l_kick_player(lua_State *L)
295 NO_MAP_LOCK_REQUIRED;
296 const char *name = luaL_checkstring(L, 1);
298 if (lua_isstring(L, 2))
300 message = std::string("Kicked: ") + lua_tostring(L, 2);
306 Player *player = getEnv(L)->getPlayer(name);
309 lua_pushboolean(L, false); // No such player
312 getServer(L)->DenyAccess_Legacy(player->peer_id, utf8_to_wide(message));
313 lua_pushboolean(L, true);
317 // unban_player_or_ip()
318 int ModApiServer::l_unban_player_or_ip(lua_State *L)
320 NO_MAP_LOCK_REQUIRED;
321 const char * ip_or_name = luaL_checkstring(L, 1);
322 getServer(L)->unsetIpBanned(ip_or_name);
323 lua_pushboolean(L, true);
327 // show_formspec(playername,formname,formspec)
328 int ModApiServer::l_show_formspec(lua_State *L)
330 NO_MAP_LOCK_REQUIRED;
331 const char *playername = luaL_checkstring(L, 1);
332 const char *formname = luaL_checkstring(L, 2);
333 const char *formspec = luaL_checkstring(L, 3);
335 if(getServer(L)->showFormspec(playername,formspec,formname))
337 lua_pushboolean(L, true);
339 lua_pushboolean(L, false);
344 // get_current_modname()
345 int ModApiServer::l_get_current_modname(lua_State *L)
347 NO_MAP_LOCK_REQUIRED;
348 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
352 // get_modpath(modname)
353 int ModApiServer::l_get_modpath(lua_State *L)
355 NO_MAP_LOCK_REQUIRED;
356 std::string modname = luaL_checkstring(L, 1);
357 const ModSpec *mod = getServer(L)->getModSpec(modname);
362 lua_pushstring(L, mod->path.c_str());
367 // the returned list is sorted alphabetically for you
368 int ModApiServer::l_get_modnames(lua_State *L)
370 NO_MAP_LOCK_REQUIRED;
372 // Get a list of mods
373 std::vector<std::string> modlist;
374 getServer(L)->getModNames(modlist);
376 // Take unsorted items from mods_unsorted and sort them into
377 // mods_sorted; not great performance but the number of mods on a
378 // server will likely be small.
379 std::sort(modlist.begin(), modlist.end());
381 // Package them up for Lua
382 lua_createtable(L, modlist.size(), 0);
383 std::vector<std::string>::iterator iter = modlist.begin();
384 for (u16 i = 0; iter != modlist.end(); iter++) {
385 lua_pushstring(L, iter->c_str());
386 lua_rawseti(L, -2, ++i);
392 int ModApiServer::l_get_worldpath(lua_State *L)
394 NO_MAP_LOCK_REQUIRED;
395 std::string worldpath = getServer(L)->getWorldPath();
396 lua_pushstring(L, worldpath.c_str());
400 // sound_play(spec, parameters)
401 int ModApiServer::l_sound_play(lua_State *L)
403 NO_MAP_LOCK_REQUIRED;
404 SimpleSoundSpec spec;
405 read_soundspec(L, 1, spec);
406 ServerSoundParams params;
407 read_server_sound_params(L, 2, params);
408 s32 handle = getServer(L)->playSound(spec, params);
409 lua_pushinteger(L, handle);
413 // sound_stop(handle)
414 int ModApiServer::l_sound_stop(lua_State *L)
416 NO_MAP_LOCK_REQUIRED;
417 int handle = luaL_checkinteger(L, 1);
418 getServer(L)->stopSound(handle);
423 int ModApiServer::l_is_singleplayer(lua_State *L)
425 NO_MAP_LOCK_REQUIRED;
426 lua_pushboolean(L, getServer(L)->isSingleplayer());
430 // notify_authentication_modified(name)
431 int ModApiServer::l_notify_authentication_modified(lua_State *L)
433 NO_MAP_LOCK_REQUIRED;
434 std::string name = "";
435 if(lua_isstring(L, 1))
436 name = lua_tostring(L, 1);
437 getServer(L)->reportPrivsModified(name);
441 // get_last_run_mod()
442 int ModApiServer::l_get_last_run_mod(lua_State *L)
444 NO_MAP_LOCK_REQUIRED;
445 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
446 const char *current_mod = lua_tostring(L, -1);
447 if (current_mod == NULL || current_mod[0] == '\0') {
449 lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
454 // set_last_run_mod(modname)
455 int ModApiServer::l_set_last_run_mod(lua_State *L)
457 NO_MAP_LOCK_REQUIRED;
458 #ifdef SCRIPTAPI_DEBUG
459 const char *mod = lua_tostring(L, 1);
460 getScriptApiBase(L)->setOriginDirect(mod);
461 //printf(">>>> last mod set from Lua: %s\n", mod);
467 // cause_error(type_of_error)
468 int ModApiServer::l_cause_error(lua_State *L)
470 NO_MAP_LOCK_REQUIRED;
471 std::string type_of_error = "none";
472 if(lua_isstring(L, 1))
473 type_of_error = lua_tostring(L, 1);
475 errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
477 if(type_of_error == "segv") {
478 volatile int* some_pointer = 0;
479 errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
481 } else if (type_of_error == "zerodivision") {
483 unsigned int some_number = porting::getTimeS();
484 unsigned int zerovalue = 0;
485 unsigned int result = some_number / zerovalue;
486 errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
488 } else if (type_of_error == "exception") {
489 throw BaseException("Errorhandler test fct called");
496 void ModApiServer::Initialize(lua_State *L, int top)
498 API_FCT(request_shutdown);
499 API_FCT(get_server_status);
500 API_FCT(get_worldpath);
501 API_FCT(is_singleplayer);
503 API_FCT(get_current_modname);
504 API_FCT(get_modpath);
505 API_FCT(get_modnames);
507 API_FCT(chat_send_all);
508 API_FCT(chat_send_player);
509 API_FCT(show_formspec);
513 API_FCT(get_player_information);
514 API_FCT(get_player_privs);
515 API_FCT(get_player_ip);
516 API_FCT(get_ban_list);
517 API_FCT(get_ban_description);
519 API_FCT(kick_player);
520 API_FCT(unban_player_or_ip);
521 API_FCT(notify_authentication_modified);
523 API_FCT(get_last_run_mod);
524 API_FCT(set_last_run_mod);
526 API_FCT(cause_error);