]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_server.cpp
Clang-format: fix some header files and remove them from whitelist
[dragonfireclient.git] / src / script / lua_api / l_server.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
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"
25 #include "server.h"
26 #include "environment.h"
27 #include "player.h"
28 #include "log.h"
29
30 // request_shutdown()
31 int ModApiServer::l_request_shutdown(lua_State *L)
32 {
33         NO_MAP_LOCK_REQUIRED;
34         const char *msg = lua_tolstring(L, 1, NULL);
35         bool reconnect = lua_toboolean(L, 2);
36         getServer(L)->requestShutdown(msg ? msg : "", reconnect);
37         return 0;
38 }
39
40 // get_server_status()
41 int ModApiServer::l_get_server_status(lua_State *L)
42 {
43         NO_MAP_LOCK_REQUIRED;
44         lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
45         return 1;
46 }
47
48 // get_server_uptime()
49 int ModApiServer::l_get_server_uptime(lua_State *L)
50 {
51         NO_MAP_LOCK_REQUIRED;
52         lua_pushnumber(L, getServer(L)->getUptime());
53         return 1;
54 }
55
56
57 // print(text)
58 int ModApiServer::l_print(lua_State *L)
59 {
60         NO_MAP_LOCK_REQUIRED;
61         std::string text;
62         text = luaL_checkstring(L, 1);
63         getServer(L)->printToConsoleOnly(text);
64         return 0;
65 }
66
67 // chat_send_all(text)
68 int ModApiServer::l_chat_send_all(lua_State *L)
69 {
70         NO_MAP_LOCK_REQUIRED;
71         const char *text = luaL_checkstring(L, 1);
72         // Get server from registry
73         Server *server = getServer(L);
74         // Send
75         server->notifyPlayers(narrow_to_wide(text));
76         return 0;
77 }
78
79 // chat_send_player(name, text)
80 int ModApiServer::l_chat_send_player(lua_State *L)
81 {
82         NO_MAP_LOCK_REQUIRED;
83         const char *name = luaL_checkstring(L, 1);
84         const char *text = luaL_checkstring(L, 2);
85
86         // Get server from registry
87         Server *server = getServer(L);
88         // Send
89         server->notifyPlayer(name, narrow_to_wide(text));
90         return 0;
91 }
92
93 // get_player_privs(name, text)
94 int ModApiServer::l_get_player_privs(lua_State *L)
95 {
96         NO_MAP_LOCK_REQUIRED;
97         const char *name = luaL_checkstring(L, 1);
98         // Get server from registry
99         Server *server = getServer(L);
100         // Do it
101         lua_newtable(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());
108         }
109         lua_pushvalue(L, table);
110         return 1;
111 }
112
113 // get_player_ip()
114 int ModApiServer::l_get_player_ip(lua_State *L)
115 {
116         NO_MAP_LOCK_REQUIRED;
117         const char * name = luaL_checkstring(L, 1);
118         RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
119         if(player == NULL)
120         {
121                 lua_pushnil(L); // no such player
122                 return 1;
123         }
124         try
125         {
126                 Address addr = getServer(L)->getPeerAddress(player->peer_id);
127                 std::string ip_str = addr.serializeString();
128                 lua_pushstring(L, ip_str.c_str());
129                 return 1;
130         }
131         catch(con::PeerNotFoundException) // unlikely
132         {
133                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
134                 lua_pushnil(L); // error
135                 return 1;
136         }
137 }
138
139 // get_player_information()
140 int ModApiServer::l_get_player_information(lua_State *L)
141 {
142
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
148                 return 1;
149         }
150
151         Address addr;
152         try
153         {
154                 addr = getServer(L)->getPeerAddress(player->peer_id);
155         }
156         catch(con::PeerNotFoundException) // unlikely
157         {
158                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
159                 lua_pushnil(L); // error
160                 return 1;
161         }
162
163         float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
164         ClientState state;
165         u32 uptime;
166         u16 prot_vers;
167         u8 ser_vers,major,minor,patch;
168         std::string vers_string;
169
170 #define ERET(code)                                                             \
171         if (!(code)) {                                                             \
172                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;     \
173                 lua_pushnil(L); /* error */                                            \
174                 return 1;                                                              \
175         }
176
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))
183
184         ERET(getServer(L)->getClientInfo(player->peer_id,
185                                                                                 &state, &uptime, &ser_vers, &prot_vers,
186                                                                                 &major, &minor, &patch, &vers_string))
187
188         lua_newtable(L);
189         int table = lua_gettop(L);
190
191         lua_pushstring(L,"address");
192         lua_pushstring(L, addr.serializeString().c_str());
193         lua_settable(L, table);
194
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);
200         } else {
201                 lua_pushnumber(L, 0);
202         }
203         lua_settable(L, table);
204
205         lua_pushstring(L,"min_rtt");
206         lua_pushnumber(L, min_rtt);
207         lua_settable(L, table);
208
209         lua_pushstring(L,"max_rtt");
210         lua_pushnumber(L, max_rtt);
211         lua_settable(L, table);
212
213         lua_pushstring(L,"avg_rtt");
214         lua_pushnumber(L, avg_rtt);
215         lua_settable(L, table);
216
217         lua_pushstring(L,"min_jitter");
218         lua_pushnumber(L, min_jitter);
219         lua_settable(L, table);
220
221         lua_pushstring(L,"max_jitter");
222         lua_pushnumber(L, max_jitter);
223         lua_settable(L, table);
224
225         lua_pushstring(L,"avg_jitter");
226         lua_pushnumber(L, avg_jitter);
227         lua_settable(L, table);
228
229         lua_pushstring(L,"connection_uptime");
230         lua_pushnumber(L, uptime);
231         lua_settable(L, table);
232
233 #ifndef NDEBUG
234         lua_pushstring(L,"serialization_version");
235         lua_pushnumber(L, ser_vers);
236         lua_settable(L, table);
237
238         lua_pushstring(L,"protocol_version");
239         lua_pushnumber(L, prot_vers);
240         lua_settable(L, table);
241
242         lua_pushstring(L,"major");
243         lua_pushnumber(L, major);
244         lua_settable(L, table);
245
246         lua_pushstring(L,"minor");
247         lua_pushnumber(L, minor);
248         lua_settable(L, table);
249
250         lua_pushstring(L,"patch");
251         lua_pushnumber(L, patch);
252         lua_settable(L, table);
253
254         lua_pushstring(L,"version_string");
255         lua_pushstring(L, vers_string.c_str());
256         lua_settable(L, table);
257
258         lua_pushstring(L,"state");
259         lua_pushstring(L,ClientInterface::state2Name(state).c_str());
260         lua_settable(L, table);
261 #endif
262
263 #undef ERET
264         return 1;
265 }
266
267 // get_ban_list()
268 int ModApiServer::l_get_ban_list(lua_State *L)
269 {
270         NO_MAP_LOCK_REQUIRED;
271         lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
272         return 1;
273 }
274
275 // get_ban_description()
276 int ModApiServer::l_get_ban_description(lua_State *L)
277 {
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());
281         return 1;
282 }
283
284 // ban_player()
285 int ModApiServer::l_ban_player(lua_State *L)
286 {
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
292                 return 1;
293         }
294         try
295         {
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);
300         }
301         catch(con::PeerNotFoundException) // unlikely
302         {
303                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
304                 lua_pushboolean(L, false); // error
305                 return 1;
306         }
307         lua_pushboolean(L, true);
308         return 1;
309 }
310
311 // kick_player(name, [reason]) -> success
312 int ModApiServer::l_kick_player(lua_State *L)
313 {
314         NO_MAP_LOCK_REQUIRED;
315         const char *name = luaL_checkstring(L, 1);
316         std::string message;
317         if (lua_isstring(L, 2))
318         {
319                 message = std::string("Kicked: ") + lua_tostring(L, 2);
320         }
321         else
322         {
323                 message = "Kicked.";
324         }
325
326         RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
327         if (player == NULL) {
328                 lua_pushboolean(L, false); // No such player
329                 return 1;
330         }
331         getServer(L)->DenyAccess_Legacy(player->peer_id, utf8_to_wide(message));
332         lua_pushboolean(L, true);
333         return 1;
334 }
335
336 // unban_player_or_ip()
337 int ModApiServer::l_unban_player_or_ip(lua_State *L)
338 {
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);
343         return 1;
344 }
345
346 // show_formspec(playername,formname,formspec)
347 int ModApiServer::l_show_formspec(lua_State *L)
348 {
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);
353
354         if(getServer(L)->showFormspec(playername,formspec,formname))
355         {
356                 lua_pushboolean(L, true);
357         }else{
358                 lua_pushboolean(L, false);
359         }
360         return 1;
361 }
362
363 // get_current_modname()
364 int ModApiServer::l_get_current_modname(lua_State *L)
365 {
366         NO_MAP_LOCK_REQUIRED;
367         lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
368         return 1;
369 }
370
371 // get_modpath(modname)
372 int ModApiServer::l_get_modpath(lua_State *L)
373 {
374         NO_MAP_LOCK_REQUIRED;
375         std::string modname = luaL_checkstring(L, 1);
376         const ModSpec *mod = getServer(L)->getModSpec(modname);
377         if (!mod) {
378                 lua_pushnil(L);
379                 return 1;
380         }
381         lua_pushstring(L, mod->path.c_str());
382         return 1;
383 }
384
385 // get_modnames()
386 // the returned list is sorted alphabetically for you
387 int ModApiServer::l_get_modnames(lua_State *L)
388 {
389         NO_MAP_LOCK_REQUIRED;
390
391         // Get a list of mods
392         std::vector<std::string> modlist;
393         getServer(L)->getModNames(modlist);
394
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());
399
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);
406         }
407         return 1;
408 }
409
410 // get_worldpath()
411 int ModApiServer::l_get_worldpath(lua_State *L)
412 {
413         NO_MAP_LOCK_REQUIRED;
414         std::string worldpath = getServer(L)->getWorldPath();
415         lua_pushstring(L, worldpath.c_str());
416         return 1;
417 }
418
419 // sound_play(spec, parameters)
420 int ModApiServer::l_sound_play(lua_State *L)
421 {
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);
429         return 1;
430 }
431
432 // sound_stop(handle)
433 int ModApiServer::l_sound_stop(lua_State *L)
434 {
435         NO_MAP_LOCK_REQUIRED;
436         int handle = luaL_checkinteger(L, 1);
437         getServer(L)->stopSound(handle);
438         return 0;
439 }
440
441 // is_singleplayer()
442 int ModApiServer::l_is_singleplayer(lua_State *L)
443 {
444         NO_MAP_LOCK_REQUIRED;
445         lua_pushboolean(L, getServer(L)->isSingleplayer());
446         return 1;
447 }
448
449 // notify_authentication_modified(name)
450 int ModApiServer::l_notify_authentication_modified(lua_State *L)
451 {
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);
457         return 0;
458 }
459
460 // get_last_run_mod()
461 int ModApiServer::l_get_last_run_mod(lua_State *L)
462 {
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') {
467                 lua_pop(L, 1);
468                 lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
469         }
470         return 1;
471 }
472
473 // set_last_run_mod(modname)
474 int ModApiServer::l_set_last_run_mod(lua_State *L)
475 {
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);
481 #endif
482         return 0;
483 }
484
485 #ifndef NDEBUG
486 // cause_error(type_of_error)
487 int ModApiServer::l_cause_error(lua_State *L)
488 {
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);
493
494         errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
495
496         if(type_of_error == "segv") {
497                 volatile int* some_pointer = 0;
498                 errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
499
500         } else if (type_of_error == "zerodivision") {
501
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;
506
507         } else if (type_of_error == "exception") {
508                 throw BaseException("Errorhandler test fct called");
509         }
510
511         return 0;
512 }
513 #endif
514
515 void ModApiServer::Initialize(lua_State *L, int top)
516 {
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);
522
523         API_FCT(get_current_modname);
524         API_FCT(get_modpath);
525         API_FCT(get_modnames);
526
527         API_FCT(print);
528
529         API_FCT(chat_send_all);
530         API_FCT(chat_send_player);
531         API_FCT(show_formspec);
532         API_FCT(sound_play);
533         API_FCT(sound_stop);
534
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);
540         API_FCT(ban_player);
541         API_FCT(kick_player);
542         API_FCT(unban_player_or_ip);
543         API_FCT(notify_authentication_modified);
544
545         API_FCT(get_last_run_mod);
546         API_FCT(set_last_run_mod);
547 #ifndef NDEBUG
548         API_FCT(cause_error);
549 #endif
550 }