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"
25 #include "environment.h"
30 int ModApiServer::l_request_shutdown(lua_State *L)
32 getServer(L)->requestShutdown();
36 // get_server_status()
37 int ModApiServer::l_get_server_status(lua_State *L)
40 lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
44 // chat_send_all(text)
45 int ModApiServer::l_chat_send_all(lua_State *L)
48 const char *text = luaL_checkstring(L, 1);
49 // Get server from registry
50 Server *server = getServer(L);
52 server->notifyPlayers(narrow_to_wide(text));
56 // chat_send_player(name, text)
57 int ModApiServer::l_chat_send_player(lua_State *L)
60 const char *name = luaL_checkstring(L, 1);
61 const char *text = luaL_checkstring(L, 2);
63 // Get server from registry
64 Server *server = getServer(L);
66 server->notifyPlayer(name, narrow_to_wide(text));
70 // get_player_privs(name, text)
71 int ModApiServer::l_get_player_privs(lua_State *L)
74 const char *name = luaL_checkstring(L, 1);
75 // Get server from registry
76 Server *server = getServer(L);
79 int table = lua_gettop(L);
80 std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
81 for(std::set<std::string>::const_iterator
82 i = privs_s.begin(); i != privs_s.end(); i++){
83 lua_pushboolean(L, true);
84 lua_setfield(L, table, i->c_str());
86 lua_pushvalue(L, table);
91 int ModApiServer::l_get_player_ip(lua_State *L)
94 const char * name = luaL_checkstring(L, 1);
95 Player *player = getEnv(L)->getPlayer(name);
98 lua_pushnil(L); // no such player
103 Address addr = getServer(L)->getPeerAddress(player->peer_id);
104 std::string ip_str = addr.serializeString();
105 lua_pushstring(L, ip_str.c_str());
108 catch(con::PeerNotFoundException) // unlikely
110 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
111 lua_pushnil(L); // error
116 // get_player_information()
117 int ModApiServer::l_get_player_information(lua_State *L)
120 NO_MAP_LOCK_REQUIRED;
121 const char * name = luaL_checkstring(L, 1);
122 Player *player = getEnv(L)->getPlayer(name);
125 lua_pushnil(L); // no such player
132 addr = getServer(L)->getPeerAddress(player->peer_id);
134 catch(con::PeerNotFoundException) // unlikely
136 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
137 lua_pushnil(L); // error
141 float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
145 u8 ser_vers,major,minor,patch;
146 std::string vers_string;
150 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; \
151 lua_pushnil(L); /* error */ \
155 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_RTT,&min_rtt))
156 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_RTT,&max_rtt))
157 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_RTT,&avg_rtt))
158 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_JITTER,&min_jitter))
159 ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_JITTER,&max_jitter))
160 ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_JITTER,&avg_jitter))
162 ERET(getServer(L)->getClientInfo(player->peer_id,
163 &state, &uptime, &ser_vers, &prot_vers,
164 &major, &minor, &patch, &vers_string))
167 int table = lua_gettop(L);
169 lua_pushstring(L,"address");
170 lua_pushstring(L, addr.serializeString().c_str());
171 lua_settable(L, table);
173 lua_pushstring(L,"ip_version");
174 if (addr.getFamily() == AF_INET) {
175 lua_pushnumber(L, 4);
176 } else if (addr.getFamily() == AF_INET6) {
177 lua_pushnumber(L, 6);
179 lua_pushnumber(L, 0);
181 lua_settable(L, table);
183 lua_pushstring(L,"min_rtt");
184 lua_pushnumber(L, min_rtt);
185 lua_settable(L, table);
187 lua_pushstring(L,"max_rtt");
188 lua_pushnumber(L, max_rtt);
189 lua_settable(L, table);
191 lua_pushstring(L,"avg_rtt");
192 lua_pushnumber(L, avg_rtt);
193 lua_settable(L, table);
195 lua_pushstring(L,"min_jitter");
196 lua_pushnumber(L, min_jitter);
197 lua_settable(L, table);
199 lua_pushstring(L,"max_jitter");
200 lua_pushnumber(L, max_jitter);
201 lua_settable(L, table);
203 lua_pushstring(L,"avg_jitter");
204 lua_pushnumber(L, avg_jitter);
205 lua_settable(L, table);
207 lua_pushstring(L,"connection_uptime");
208 lua_pushnumber(L, uptime);
209 lua_settable(L, table);
212 lua_pushstring(L,"serialization_version");
213 lua_pushnumber(L, ser_vers);
214 lua_settable(L, table);
216 lua_pushstring(L,"protocol_version");
217 lua_pushnumber(L, prot_vers);
218 lua_settable(L, table);
220 lua_pushstring(L,"major");
221 lua_pushnumber(L, major);
222 lua_settable(L, table);
224 lua_pushstring(L,"minor");
225 lua_pushnumber(L, minor);
226 lua_settable(L, table);
228 lua_pushstring(L,"patch");
229 lua_pushnumber(L, patch);
230 lua_settable(L, table);
232 lua_pushstring(L,"version_string");
233 lua_pushstring(L, vers_string.c_str());
234 lua_settable(L, table);
236 lua_pushstring(L,"state");
237 lua_pushstring(L,ClientInterface::state2Name(state).c_str());
238 lua_settable(L, table);
246 int ModApiServer::l_get_ban_list(lua_State *L)
248 NO_MAP_LOCK_REQUIRED;
249 lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
253 // get_ban_description()
254 int ModApiServer::l_get_ban_description(lua_State *L)
256 NO_MAP_LOCK_REQUIRED;
257 const char * ip_or_name = luaL_checkstring(L, 1);
258 lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
263 int ModApiServer::l_ban_player(lua_State *L)
265 NO_MAP_LOCK_REQUIRED;
266 const char * name = luaL_checkstring(L, 1);
267 Player *player = getEnv(L)->getPlayer(name);
270 lua_pushboolean(L, false); // no such player
275 Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
276 std::string ip_str = addr.serializeString();
277 getServer(L)->setIpBanned(ip_str, name);
279 catch(con::PeerNotFoundException) // unlikely
281 dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
282 lua_pushboolean(L, false); // error
285 lua_pushboolean(L, true);
289 // kick_player(name, [reason]) -> success
290 int ModApiServer::l_kick_player(lua_State *L)
292 NO_MAP_LOCK_REQUIRED;
293 const char *name = luaL_checkstring(L, 1);
295 if (lua_isstring(L, 2))
297 message = std::string("Kicked: ") + lua_tostring(L, 2);
303 Player *player = getEnv(L)->getPlayer(name);
306 lua_pushboolean(L, false); // No such player
309 getServer(L)->DenyAccess(player->peer_id, narrow_to_wide(message));
310 lua_pushboolean(L, true);
314 // unban_player_or_ip()
315 int ModApiServer::l_unban_player_or_ip(lua_State *L)
317 NO_MAP_LOCK_REQUIRED;
318 const char * ip_or_name = luaL_checkstring(L, 1);
319 getServer(L)->unsetIpBanned(ip_or_name);
320 lua_pushboolean(L, true);
324 // show_formspec(playername,formname,formspec)
325 int ModApiServer::l_show_formspec(lua_State *L)
327 NO_MAP_LOCK_REQUIRED;
328 const char *playername = luaL_checkstring(L, 1);
329 const char *formname = luaL_checkstring(L, 2);
330 const char *formspec = luaL_checkstring(L, 3);
332 if(getServer(L)->showFormspec(playername,formspec,formname))
334 lua_pushboolean(L, true);
336 lua_pushboolean(L, false);
341 // get_current_modname()
342 int ModApiServer::l_get_current_modname(lua_State *L)
344 NO_MAP_LOCK_REQUIRED;
345 lua_getfield(L, LUA_REGISTRYINDEX, "current_modname");
349 // get_modpath(modname)
350 int ModApiServer::l_get_modpath(lua_State *L)
352 NO_MAP_LOCK_REQUIRED;
353 std::string modname = luaL_checkstring(L, 1);
354 const ModSpec *mod = getServer(L)->getModSpec(modname);
359 lua_pushstring(L, mod->path.c_str());
364 // the returned list is sorted alphabetically for you
365 int ModApiServer::l_get_modnames(lua_State *L)
367 NO_MAP_LOCK_REQUIRED;
369 // Get a list of mods
370 std::list<std::string> mods_unsorted, mods_sorted;
371 getServer(L)->getModNames(mods_unsorted);
373 // Take unsorted items from mods_unsorted and sort them into
374 // mods_sorted; not great performance but the number of mods on a
375 // server will likely be small.
376 for(std::list<std::string>::iterator i = mods_unsorted.begin();
377 i != mods_unsorted.end(); ++i) {
379 for(std::list<std::string>::iterator x = mods_sorted.begin();
380 x != mods_sorted.end(); ++x) {
381 // I doubt anybody using Minetest will be using
382 // anything not ASCII based :)
383 if(i->compare(*x) <= 0) {
384 mods_sorted.insert(x, *i);
390 mods_sorted.push_back(*i);
393 // Package them up for Lua
394 lua_createtable(L, mods_sorted.size(), 0);
395 std::list<std::string>::iterator iter = mods_sorted.begin();
396 for (u16 i = 0; iter != mods_sorted.end(); iter++) {
397 lua_pushstring(L, iter->c_str());
398 lua_rawseti(L, -2, ++i);
404 int ModApiServer::l_get_worldpath(lua_State *L)
406 NO_MAP_LOCK_REQUIRED;
407 std::string worldpath = getServer(L)->getWorldPath();
408 lua_pushstring(L, worldpath.c_str());
412 // sound_play(spec, parameters)
413 int ModApiServer::l_sound_play(lua_State *L)
415 NO_MAP_LOCK_REQUIRED;
416 SimpleSoundSpec spec;
417 read_soundspec(L, 1, spec);
418 ServerSoundParams params;
419 read_server_sound_params(L, 2, params);
420 s32 handle = getServer(L)->playSound(spec, params);
421 lua_pushinteger(L, handle);
425 // sound_stop(handle)
426 int ModApiServer::l_sound_stop(lua_State *L)
428 NO_MAP_LOCK_REQUIRED;
429 int handle = luaL_checkinteger(L, 1);
430 getServer(L)->stopSound(handle);
435 int ModApiServer::l_is_singleplayer(lua_State *L)
437 NO_MAP_LOCK_REQUIRED;
438 lua_pushboolean(L, getServer(L)->isSingleplayer());
442 // notify_authentication_modified(name)
443 int ModApiServer::l_notify_authentication_modified(lua_State *L)
445 NO_MAP_LOCK_REQUIRED;
446 std::string name = "";
447 if(lua_isstring(L, 1))
448 name = lua_tostring(L, 1);
449 getServer(L)->reportPrivsModified(name);
454 // cause_error(type_of_error)
455 int ModApiServer::l_cause_error(lua_State *L)
457 NO_MAP_LOCK_REQUIRED;
458 std::string type_of_error = "none";
459 if(lua_isstring(L, 1))
460 type_of_error = lua_tostring(L, 1);
462 errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
464 if(type_of_error == "segv") {
465 volatile int* some_pointer = 0;
466 errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
468 } else if (type_of_error == "zerodivision") {
470 unsigned int some_number = porting::getTimeS();
471 unsigned int zerovalue = 0;
472 unsigned int result = some_number / zerovalue;
473 errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
475 } else if (type_of_error == "exception") {
476 throw BaseException("Errorhandler test fct called");
483 void ModApiServer::Initialize(lua_State *L, int top)
485 API_FCT(request_shutdown);
486 API_FCT(get_server_status);
487 API_FCT(get_worldpath);
488 API_FCT(is_singleplayer);
490 API_FCT(get_current_modname);
491 API_FCT(get_modpath);
492 API_FCT(get_modnames);
494 API_FCT(chat_send_all);
495 API_FCT(chat_send_player);
496 API_FCT(show_formspec);
500 API_FCT(get_player_information);
501 API_FCT(get_player_privs);
502 API_FCT(get_player_ip);
503 API_FCT(get_ban_list);
504 API_FCT(get_ban_description);
506 API_FCT(kick_player);
507 API_FCT(unban_player_or_ip);
508 API_FCT(notify_authentication_modified);
511 API_FCT(cause_error);