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());
48 // get_server_uptime()
49 int ModApiServer::l_get_server_uptime(lua_State *L)
52 lua_pushnumber(L, getServer(L)->getUptime());
58 int ModApiServer::l_print(lua_State *L)
62 text = luaL_checkstring(L, 1);
63 getServer(L)->printToConsoleOnly(text);
67 // chat_send_all(text)
68 int ModApiServer::l_chat_send_all(lua_State *L)
71 const char *text = luaL_checkstring(L, 1);
72 // Get server from registry
73 Server *server = getServer(L);
75 server->notifyPlayers(narrow_to_wide(text));
79 // chat_send_player(name, text)
80 int ModApiServer::l_chat_send_player(lua_State *L)
83 const char *name = luaL_checkstring(L, 1);
84 const char *text = luaL_checkstring(L, 2);
86 // Get server from registry
87 Server *server = getServer(L);
89 server->notifyPlayer(name, narrow_to_wide(text));
93 // get_player_privs(name, text)
94 int ModApiServer::l_get_player_privs(lua_State *L)
97 const char *name = luaL_checkstring(L, 1);
98 // Get server from registry
99 Server *server = getServer(L);
102 int table = lua_gettop(L);
103 std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
104 for(std::set<std::string>::const_iterator
105 i = privs_s.begin(); i != privs_s.end(); i++){
106 lua_pushboolean(L, true);
107 lua_setfield(L, table, i->c_str());
109 lua_pushvalue(L, table);
114 int ModApiServer::l_get_player_ip(lua_State *L)
116 NO_MAP_LOCK_REQUIRED;
117 const char * name = luaL_checkstring(L, 1);
118 RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
121 lua_pushnil(L); // no such player
126 Address addr = getServer(L)->getPeerAddress(player->peer_id);
127 std::string ip_str = addr.serializeString();
128 lua_pushstring(L, ip_str.c_str());
131 catch(con::PeerNotFoundException) // unlikely
133 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
134 lua_pushnil(L); // error
139 // get_player_information()
140 int ModApiServer::l_get_player_information(lua_State *L)
143 NO_MAP_LOCK_REQUIRED;
144 const char * name = luaL_checkstring(L, 1);
145 RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
146 if (player == NULL) {
147 lua_pushnil(L); // no such player
154 addr = getServer(L)->getPeerAddress(player->peer_id);
156 catch(con::PeerNotFoundException) // unlikely
158 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
159 lua_pushnil(L); // error
163 float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
167 u8 ser_vers,major,minor,patch;
168 std::string vers_string;
172 dstream << FUNCTION_NAME << ": peer was not found" << std::endl; \
173 lua_pushnil(L); /* error */ \
177 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_RTT,&min_rtt))
178 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_RTT,&max_rtt))
179 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_RTT,&avg_rtt))
180 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_JITTER,&min_jitter))
181 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_JITTER,&max_jitter))
182 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_JITTER,&avg_jitter))
184 ERET(getServer(L)->getClientInfo(player->peer_id,
185 &state, &uptime, &ser_vers, &prot_vers,
186 &major, &minor, &patch, &vers_string))
189 int table = lua_gettop(L);
191 lua_pushstring(L,"address");
192 lua_pushstring(L, addr.serializeString().c_str());
193 lua_settable(L, table);
195 lua_pushstring(L,"ip_version");
196 if (addr.getFamily() == AF_INET) {
197 lua_pushnumber(L, 4);
198 } else if (addr.getFamily() == AF_INET6) {
199 lua_pushnumber(L, 6);
201 lua_pushnumber(L, 0);
203 lua_settable(L, table);
205 lua_pushstring(L,"min_rtt");
206 lua_pushnumber(L, min_rtt);
207 lua_settable(L, table);
209 lua_pushstring(L,"max_rtt");
210 lua_pushnumber(L, max_rtt);
211 lua_settable(L, table);
213 lua_pushstring(L,"avg_rtt");
214 lua_pushnumber(L, avg_rtt);
215 lua_settable(L, table);
217 lua_pushstring(L,"min_jitter");
218 lua_pushnumber(L, min_jitter);
219 lua_settable(L, table);
221 lua_pushstring(L,"max_jitter");
222 lua_pushnumber(L, max_jitter);
223 lua_settable(L, table);
225 lua_pushstring(L,"avg_jitter");
226 lua_pushnumber(L, avg_jitter);
227 lua_settable(L, table);
229 lua_pushstring(L,"connection_uptime");
230 lua_pushnumber(L, uptime);
231 lua_settable(L, table);
234 lua_pushstring(L,"serialization_version");
235 lua_pushnumber(L, ser_vers);
236 lua_settable(L, table);
238 lua_pushstring(L,"protocol_version");
239 lua_pushnumber(L, prot_vers);
240 lua_settable(L, table);
242 lua_pushstring(L,"major");
243 lua_pushnumber(L, major);
244 lua_settable(L, table);
246 lua_pushstring(L,"minor");
247 lua_pushnumber(L, minor);
248 lua_settable(L, table);
250 lua_pushstring(L,"patch");
251 lua_pushnumber(L, patch);
252 lua_settable(L, table);
254 lua_pushstring(L,"version_string");
255 lua_pushstring(L, vers_string.c_str());
256 lua_settable(L, table);
258 lua_pushstring(L,"state");
259 lua_pushstring(L,ClientInterface::state2Name(state).c_str());
260 lua_settable(L, table);
268 int ModApiServer::l_get_ban_list(lua_State *L)
270 NO_MAP_LOCK_REQUIRED;
271 lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
275 // get_ban_description()
276 int ModApiServer::l_get_ban_description(lua_State *L)
278 NO_MAP_LOCK_REQUIRED;
279 const char * ip_or_name = luaL_checkstring(L, 1);
280 lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
285 int ModApiServer::l_ban_player(lua_State *L)
287 NO_MAP_LOCK_REQUIRED;
288 const char * name = luaL_checkstring(L, 1);
289 RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
290 if (player == NULL) {
291 lua_pushboolean(L, false); // no such player
296 Address addr = getServer(L)->getPeerAddress(
297 dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name)->peer_id);
298 std::string ip_str = addr.serializeString();
299 getServer(L)->setIpBanned(ip_str, name);
301 catch(con::PeerNotFoundException) // unlikely
303 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
304 lua_pushboolean(L, false); // error
307 lua_pushboolean(L, true);
311 // kick_player(name, [reason]) -> success
312 int ModApiServer::l_kick_player(lua_State *L)
314 NO_MAP_LOCK_REQUIRED;
315 const char *name = luaL_checkstring(L, 1);
317 if (lua_isstring(L, 2))
319 message = std::string("Kicked: ") + lua_tostring(L, 2);
326 RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
327 if (player == NULL) {
328 lua_pushboolean(L, false); // No such player
331 getServer(L)->DenyAccess_Legacy(player->peer_id, utf8_to_wide(message));
332 lua_pushboolean(L, true);
336 // unban_player_or_ip()
337 int ModApiServer::l_unban_player_or_ip(lua_State *L)
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);
346 // show_formspec(playername,formname,formspec)
347 int ModApiServer::l_show_formspec(lua_State *L)
349 NO_MAP_LOCK_REQUIRED;
350 const char *playername = luaL_checkstring(L, 1);
351 const char *formname = luaL_checkstring(L, 2);
352 const char *formspec = luaL_checkstring(L, 3);
354 if(getServer(L)->showFormspec(playername,formspec,formname))
356 lua_pushboolean(L, true);
358 lua_pushboolean(L, false);
363 // get_current_modname()
364 int ModApiServer::l_get_current_modname(lua_State *L)
366 NO_MAP_LOCK_REQUIRED;
367 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
371 // get_modpath(modname)
372 int ModApiServer::l_get_modpath(lua_State *L)
374 NO_MAP_LOCK_REQUIRED;
375 std::string modname = luaL_checkstring(L, 1);
376 const ModSpec *mod = getServer(L)->getModSpec(modname);
381 lua_pushstring(L, mod->path.c_str());
386 // the returned list is sorted alphabetically for you
387 int ModApiServer::l_get_modnames(lua_State *L)
389 NO_MAP_LOCK_REQUIRED;
391 // Get a list of mods
392 std::vector<std::string> modlist;
393 getServer(L)->getModNames(modlist);
395 // Take unsorted items from mods_unsorted and sort them into
396 // mods_sorted; not great performance but the number of mods on a
397 // server will likely be small.
398 std::sort(modlist.begin(), modlist.end());
400 // Package them up for Lua
401 lua_createtable(L, modlist.size(), 0);
402 std::vector<std::string>::iterator iter = modlist.begin();
403 for (u16 i = 0; iter != modlist.end(); iter++) {
404 lua_pushstring(L, iter->c_str());
405 lua_rawseti(L, -2, ++i);
411 int ModApiServer::l_get_worldpath(lua_State *L)
413 NO_MAP_LOCK_REQUIRED;
414 std::string worldpath = getServer(L)->getWorldPath();
415 lua_pushstring(L, worldpath.c_str());
419 // sound_play(spec, parameters)
420 int ModApiServer::l_sound_play(lua_State *L)
422 NO_MAP_LOCK_REQUIRED;
423 SimpleSoundSpec spec;
424 read_soundspec(L, 1, spec);
425 ServerSoundParams params;
426 read_server_sound_params(L, 2, params);
427 s32 handle = getServer(L)->playSound(spec, params);
428 lua_pushinteger(L, handle);
432 // sound_stop(handle)
433 int ModApiServer::l_sound_stop(lua_State *L)
435 NO_MAP_LOCK_REQUIRED;
436 int handle = luaL_checkinteger(L, 1);
437 getServer(L)->stopSound(handle);
442 int ModApiServer::l_is_singleplayer(lua_State *L)
444 NO_MAP_LOCK_REQUIRED;
445 lua_pushboolean(L, getServer(L)->isSingleplayer());
449 // notify_authentication_modified(name)
450 int ModApiServer::l_notify_authentication_modified(lua_State *L)
452 NO_MAP_LOCK_REQUIRED;
453 std::string name = "";
454 if(lua_isstring(L, 1))
455 name = lua_tostring(L, 1);
456 getServer(L)->reportPrivsModified(name);
460 // get_last_run_mod()
461 int ModApiServer::l_get_last_run_mod(lua_State *L)
463 NO_MAP_LOCK_REQUIRED;
464 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
465 const char *current_mod = lua_tostring(L, -1);
466 if (current_mod == NULL || current_mod[0] == '\0') {
468 lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
473 // set_last_run_mod(modname)
474 int ModApiServer::l_set_last_run_mod(lua_State *L)
476 NO_MAP_LOCK_REQUIRED;
477 #ifdef SCRIPTAPI_DEBUG
478 const char *mod = lua_tostring(L, 1);
479 getScriptApiBase(L)->setOriginDirect(mod);
480 //printf(">>>> last mod set from Lua: %s\n", mod);
486 // cause_error(type_of_error)
487 int ModApiServer::l_cause_error(lua_State *L)
489 NO_MAP_LOCK_REQUIRED;
490 std::string type_of_error = "none";
491 if(lua_isstring(L, 1))
492 type_of_error = lua_tostring(L, 1);
494 errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
496 if(type_of_error == "segv") {
497 volatile int* some_pointer = 0;
498 errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
500 } else if (type_of_error == "zerodivision") {
502 unsigned int some_number = porting::getTimeS();
503 unsigned int zerovalue = 0;
504 unsigned int result = some_number / zerovalue;
505 errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
507 } else if (type_of_error == "exception") {
508 throw BaseException("Errorhandler test fct called");
515 void ModApiServer::Initialize(lua_State *L, int top)
517 API_FCT(request_shutdown);
518 API_FCT(get_server_status);
519 API_FCT(get_server_uptime);
520 API_FCT(get_worldpath);
521 API_FCT(is_singleplayer);
523 API_FCT(get_current_modname);
524 API_FCT(get_modpath);
525 API_FCT(get_modnames);
529 API_FCT(chat_send_all);
530 API_FCT(chat_send_player);
531 API_FCT(show_formspec);
535 API_FCT(get_player_information);
536 API_FCT(get_player_privs);
537 API_FCT(get_player_ip);
538 API_FCT(get_ban_list);
539 API_FCT(get_ban_description);
541 API_FCT(kick_player);
542 API_FCT(unban_player_or_ip);
543 API_FCT(notify_authentication_modified);
545 API_FCT(get_last_run_mod);
546 API_FCT(set_last_run_mod);
548 API_FCT(cause_error);