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::vector<std::string> mods_unsorted;
371 std::list<std::string> mods_sorted;
372 getServer(L)->getModNames(mods_unsorted);
374 // Take unsorted items from mods_unsorted and sort them into
375 // mods_sorted; not great performance but the number of mods on a
376 // server will likely be small.
377 for(std::vector<std::string>::iterator i = mods_unsorted.begin();
378 i != mods_unsorted.end(); ++i) {
380 for(std::list<std::string>::iterator x = mods_sorted.begin();
381 x != mods_sorted.end(); ++x) {
382 // I doubt anybody using Minetest will be using
383 // anything not ASCII based :)
384 if(i->compare(*x) <= 0) {
385 mods_sorted.insert(x, *i);
391 mods_sorted.push_back(*i);
394 // Package them up for Lua
395 lua_createtable(L, mods_sorted.size(), 0);
396 std::list<std::string>::iterator iter = mods_sorted.begin();
397 for (u16 i = 0; iter != mods_sorted.end(); iter++) {
398 lua_pushstring(L, iter->c_str());
399 lua_rawseti(L, -2, ++i);
405 int ModApiServer::l_get_worldpath(lua_State *L)
407 NO_MAP_LOCK_REQUIRED;
408 std::string worldpath = getServer(L)->getWorldPath();
409 lua_pushstring(L, worldpath.c_str());
413 // sound_play(spec, parameters)
414 int ModApiServer::l_sound_play(lua_State *L)
416 NO_MAP_LOCK_REQUIRED;
417 SimpleSoundSpec spec;
418 read_soundspec(L, 1, spec);
419 ServerSoundParams params;
420 read_server_sound_params(L, 2, params);
421 s32 handle = getServer(L)->playSound(spec, params);
422 lua_pushinteger(L, handle);
426 // sound_stop(handle)
427 int ModApiServer::l_sound_stop(lua_State *L)
429 NO_MAP_LOCK_REQUIRED;
430 int handle = luaL_checkinteger(L, 1);
431 getServer(L)->stopSound(handle);
436 int ModApiServer::l_is_singleplayer(lua_State *L)
438 NO_MAP_LOCK_REQUIRED;
439 lua_pushboolean(L, getServer(L)->isSingleplayer());
443 // notify_authentication_modified(name)
444 int ModApiServer::l_notify_authentication_modified(lua_State *L)
446 NO_MAP_LOCK_REQUIRED;
447 std::string name = "";
448 if(lua_isstring(L, 1))
449 name = lua_tostring(L, 1);
450 getServer(L)->reportPrivsModified(name);
455 // cause_error(type_of_error)
456 int ModApiServer::l_cause_error(lua_State *L)
458 NO_MAP_LOCK_REQUIRED;
459 std::string type_of_error = "none";
460 if(lua_isstring(L, 1))
461 type_of_error = lua_tostring(L, 1);
463 errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
465 if(type_of_error == "segv") {
466 volatile int* some_pointer = 0;
467 errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
469 } else if (type_of_error == "zerodivision") {
471 unsigned int some_number = porting::getTimeS();
472 unsigned int zerovalue = 0;
473 unsigned int result = some_number / zerovalue;
474 errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
476 } else if (type_of_error == "exception") {
477 throw BaseException("Errorhandler test fct called");
484 void ModApiServer::Initialize(lua_State *L, int top)
486 API_FCT(request_shutdown);
487 API_FCT(get_server_status);
488 API_FCT(get_worldpath);
489 API_FCT(is_singleplayer);
491 API_FCT(get_current_modname);
492 API_FCT(get_modpath);
493 API_FCT(get_modnames);
495 API_FCT(chat_send_all);
496 API_FCT(chat_send_player);
497 API_FCT(show_formspec);
501 API_FCT(get_player_information);
502 API_FCT(get_player_privs);
503 API_FCT(get_player_ip);
504 API_FCT(get_ban_list);
505 API_FCT(get_ban_description);
507 API_FCT(kick_player);
508 API_FCT(unban_player_or_ip);
509 API_FCT(notify_authentication_modified);
512 API_FCT(cause_error);