]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_server.cpp
Add server side ncurses terminal
[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 // print(text)
49 int ModApiServer::l_print(lua_State *L)
50 {
51         NO_MAP_LOCK_REQUIRED;
52         std::string text;
53         text = luaL_checkstring(L, 1);
54         getServer(L)->printToConsoleOnly(text);
55         return 0;
56 }
57
58 // chat_send_all(text)
59 int ModApiServer::l_chat_send_all(lua_State *L)
60 {
61         NO_MAP_LOCK_REQUIRED;
62         const char *text = luaL_checkstring(L, 1);
63         // Get server from registry
64         Server *server = getServer(L);
65         // Send
66         server->notifyPlayers(narrow_to_wide(text));
67         return 0;
68 }
69
70 // chat_send_player(name, text)
71 int ModApiServer::l_chat_send_player(lua_State *L)
72 {
73         NO_MAP_LOCK_REQUIRED;
74         const char *name = luaL_checkstring(L, 1);
75         const char *text = luaL_checkstring(L, 2);
76
77         // Get server from registry
78         Server *server = getServer(L);
79         // Send
80         server->notifyPlayer(name, narrow_to_wide(text));
81         return 0;
82 }
83
84 // get_player_privs(name, text)
85 int ModApiServer::l_get_player_privs(lua_State *L)
86 {
87         NO_MAP_LOCK_REQUIRED;
88         const char *name = luaL_checkstring(L, 1);
89         // Get server from registry
90         Server *server = getServer(L);
91         // Do it
92         lua_newtable(L);
93         int table = lua_gettop(L);
94         std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
95         for(std::set<std::string>::const_iterator
96                         i = privs_s.begin(); i != privs_s.end(); i++){
97                 lua_pushboolean(L, true);
98                 lua_setfield(L, table, i->c_str());
99         }
100         lua_pushvalue(L, table);
101         return 1;
102 }
103
104 // get_player_ip()
105 int ModApiServer::l_get_player_ip(lua_State *L)
106 {
107         NO_MAP_LOCK_REQUIRED;
108         const char * name = luaL_checkstring(L, 1);
109         Player *player = getEnv(L)->getPlayer(name);
110         if(player == NULL)
111         {
112                 lua_pushnil(L); // no such player
113                 return 1;
114         }
115         try
116         {
117                 Address addr = getServer(L)->getPeerAddress(player->peer_id);
118                 std::string ip_str = addr.serializeString();
119                 lua_pushstring(L, ip_str.c_str());
120                 return 1;
121         }
122         catch(con::PeerNotFoundException) // unlikely
123         {
124                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
125                 lua_pushnil(L); // error
126                 return 1;
127         }
128 }
129
130 // get_player_information()
131 int ModApiServer::l_get_player_information(lua_State *L)
132 {
133
134         NO_MAP_LOCK_REQUIRED;
135         const char * name = luaL_checkstring(L, 1);
136         Player *player = getEnv(L)->getPlayer(name);
137         if(player == NULL)
138         {
139                 lua_pushnil(L); // no such player
140                 return 1;
141         }
142
143         Address addr;
144         try
145         {
146                 addr = getServer(L)->getPeerAddress(player->peer_id);
147         }
148         catch(con::PeerNotFoundException) // unlikely
149         {
150                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
151                 lua_pushnil(L); // error
152                 return 1;
153         }
154
155         float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
156         ClientState state;
157         u32 uptime;
158         u16 prot_vers;
159         u8 ser_vers,major,minor,patch;
160         std::string vers_string;
161
162 #define ERET(code)                                                             \
163         if (!(code)) {                                                             \
164                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;     \
165                 lua_pushnil(L); /* error */                                            \
166                 return 1;                                                              \
167         }
168
169         ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_RTT,&min_rtt))
170         ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_RTT,&max_rtt))
171         ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_RTT,&avg_rtt))
172         ERET(getServer(L)->getClientConInfo(player->peer_id,con::MIN_JITTER,&min_jitter))
173         ERET(getServer(L)->getClientConInfo(player->peer_id,con::MAX_JITTER,&max_jitter))
174         ERET(getServer(L)->getClientConInfo(player->peer_id,con::AVG_JITTER,&avg_jitter))
175
176         ERET(getServer(L)->getClientInfo(player->peer_id,
177                                                                                 &state, &uptime, &ser_vers, &prot_vers,
178                                                                                 &major, &minor, &patch, &vers_string))
179
180         lua_newtable(L);
181         int table = lua_gettop(L);
182
183         lua_pushstring(L,"address");
184         lua_pushstring(L, addr.serializeString().c_str());
185         lua_settable(L, table);
186
187         lua_pushstring(L,"ip_version");
188         if (addr.getFamily() == AF_INET) {
189                 lua_pushnumber(L, 4);
190         } else if (addr.getFamily() == AF_INET6) {
191                 lua_pushnumber(L, 6);
192         } else {
193                 lua_pushnumber(L, 0);
194         }
195         lua_settable(L, table);
196
197         lua_pushstring(L,"min_rtt");
198         lua_pushnumber(L, min_rtt);
199         lua_settable(L, table);
200
201         lua_pushstring(L,"max_rtt");
202         lua_pushnumber(L, max_rtt);
203         lua_settable(L, table);
204
205         lua_pushstring(L,"avg_rtt");
206         lua_pushnumber(L, avg_rtt);
207         lua_settable(L, table);
208
209         lua_pushstring(L,"min_jitter");
210         lua_pushnumber(L, min_jitter);
211         lua_settable(L, table);
212
213         lua_pushstring(L,"max_jitter");
214         lua_pushnumber(L, max_jitter);
215         lua_settable(L, table);
216
217         lua_pushstring(L,"avg_jitter");
218         lua_pushnumber(L, avg_jitter);
219         lua_settable(L, table);
220
221         lua_pushstring(L,"connection_uptime");
222         lua_pushnumber(L, uptime);
223         lua_settable(L, table);
224
225 #ifndef NDEBUG
226         lua_pushstring(L,"serialization_version");
227         lua_pushnumber(L, ser_vers);
228         lua_settable(L, table);
229
230         lua_pushstring(L,"protocol_version");
231         lua_pushnumber(L, prot_vers);
232         lua_settable(L, table);
233
234         lua_pushstring(L,"major");
235         lua_pushnumber(L, major);
236         lua_settable(L, table);
237
238         lua_pushstring(L,"minor");
239         lua_pushnumber(L, minor);
240         lua_settable(L, table);
241
242         lua_pushstring(L,"patch");
243         lua_pushnumber(L, patch);
244         lua_settable(L, table);
245
246         lua_pushstring(L,"version_string");
247         lua_pushstring(L, vers_string.c_str());
248         lua_settable(L, table);
249
250         lua_pushstring(L,"state");
251         lua_pushstring(L,ClientInterface::state2Name(state).c_str());
252         lua_settable(L, table);
253 #endif
254
255 #undef ERET
256         return 1;
257 }
258
259 // get_ban_list()
260 int ModApiServer::l_get_ban_list(lua_State *L)
261 {
262         NO_MAP_LOCK_REQUIRED;
263         lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
264         return 1;
265 }
266
267 // get_ban_description()
268 int ModApiServer::l_get_ban_description(lua_State *L)
269 {
270         NO_MAP_LOCK_REQUIRED;
271         const char * ip_or_name = luaL_checkstring(L, 1);
272         lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
273         return 1;
274 }
275
276 // ban_player()
277 int ModApiServer::l_ban_player(lua_State *L)
278 {
279         NO_MAP_LOCK_REQUIRED;
280         const char * name = luaL_checkstring(L, 1);
281         Player *player = getEnv(L)->getPlayer(name);
282         if(player == NULL)
283         {
284                 lua_pushboolean(L, false); // no such player
285                 return 1;
286         }
287         try
288         {
289                 Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
290                 std::string ip_str = addr.serializeString();
291                 getServer(L)->setIpBanned(ip_str, name);
292         }
293         catch(con::PeerNotFoundException) // unlikely
294         {
295                 dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
296                 lua_pushboolean(L, false); // error
297                 return 1;
298         }
299         lua_pushboolean(L, true);
300         return 1;
301 }
302
303 // kick_player(name, [reason]) -> success
304 int ModApiServer::l_kick_player(lua_State *L)
305 {
306         NO_MAP_LOCK_REQUIRED;
307         const char *name = luaL_checkstring(L, 1);
308         std::string message;
309         if (lua_isstring(L, 2))
310         {
311                 message = std::string("Kicked: ") + lua_tostring(L, 2);
312         }
313         else
314         {
315                 message = "Kicked.";
316         }
317         Player *player = getEnv(L)->getPlayer(name);
318         if (player == NULL)
319         {
320                 lua_pushboolean(L, false); // No such player
321                 return 1;
322         }
323         getServer(L)->DenyAccess_Legacy(player->peer_id, utf8_to_wide(message));
324         lua_pushboolean(L, true);
325         return 1;
326 }
327
328 // unban_player_or_ip()
329 int ModApiServer::l_unban_player_or_ip(lua_State *L)
330 {
331         NO_MAP_LOCK_REQUIRED;
332         const char * ip_or_name = luaL_checkstring(L, 1);
333         getServer(L)->unsetIpBanned(ip_or_name);
334         lua_pushboolean(L, true);
335         return 1;
336 }
337
338 // show_formspec(playername,formname,formspec)
339 int ModApiServer::l_show_formspec(lua_State *L)
340 {
341         NO_MAP_LOCK_REQUIRED;
342         const char *playername = luaL_checkstring(L, 1);
343         const char *formname = luaL_checkstring(L, 2);
344         const char *formspec = luaL_checkstring(L, 3);
345
346         if(getServer(L)->showFormspec(playername,formspec,formname))
347         {
348                 lua_pushboolean(L, true);
349         }else{
350                 lua_pushboolean(L, false);
351         }
352         return 1;
353 }
354
355 // get_current_modname()
356 int ModApiServer::l_get_current_modname(lua_State *L)
357 {
358         NO_MAP_LOCK_REQUIRED;
359         lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
360         return 1;
361 }
362
363 // get_modpath(modname)
364 int ModApiServer::l_get_modpath(lua_State *L)
365 {
366         NO_MAP_LOCK_REQUIRED;
367         std::string modname = luaL_checkstring(L, 1);
368         const ModSpec *mod = getServer(L)->getModSpec(modname);
369         if (!mod) {
370                 lua_pushnil(L);
371                 return 1;
372         }
373         lua_pushstring(L, mod->path.c_str());
374         return 1;
375 }
376
377 // get_modnames()
378 // the returned list is sorted alphabetically for you
379 int ModApiServer::l_get_modnames(lua_State *L)
380 {
381         NO_MAP_LOCK_REQUIRED;
382
383         // Get a list of mods
384         std::vector<std::string> modlist;
385         getServer(L)->getModNames(modlist);
386
387         // Take unsorted items from mods_unsorted and sort them into
388         // mods_sorted; not great performance but the number of mods on a
389         // server will likely be small.
390         std::sort(modlist.begin(), modlist.end());
391
392         // Package them up for Lua
393         lua_createtable(L, modlist.size(), 0);
394         std::vector<std::string>::iterator iter = modlist.begin();
395         for (u16 i = 0; iter != modlist.end(); iter++) {
396                 lua_pushstring(L, iter->c_str());
397                 lua_rawseti(L, -2, ++i);
398         }
399         return 1;
400 }
401
402 // get_worldpath()
403 int ModApiServer::l_get_worldpath(lua_State *L)
404 {
405         NO_MAP_LOCK_REQUIRED;
406         std::string worldpath = getServer(L)->getWorldPath();
407         lua_pushstring(L, worldpath.c_str());
408         return 1;
409 }
410
411 // sound_play(spec, parameters)
412 int ModApiServer::l_sound_play(lua_State *L)
413 {
414         NO_MAP_LOCK_REQUIRED;
415         SimpleSoundSpec spec;
416         read_soundspec(L, 1, spec);
417         ServerSoundParams params;
418         read_server_sound_params(L, 2, params);
419         s32 handle = getServer(L)->playSound(spec, params);
420         lua_pushinteger(L, handle);
421         return 1;
422 }
423
424 // sound_stop(handle)
425 int ModApiServer::l_sound_stop(lua_State *L)
426 {
427         NO_MAP_LOCK_REQUIRED;
428         int handle = luaL_checkinteger(L, 1);
429         getServer(L)->stopSound(handle);
430         return 0;
431 }
432
433 // is_singleplayer()
434 int ModApiServer::l_is_singleplayer(lua_State *L)
435 {
436         NO_MAP_LOCK_REQUIRED;
437         lua_pushboolean(L, getServer(L)->isSingleplayer());
438         return 1;
439 }
440
441 // notify_authentication_modified(name)
442 int ModApiServer::l_notify_authentication_modified(lua_State *L)
443 {
444         NO_MAP_LOCK_REQUIRED;
445         std::string name = "";
446         if(lua_isstring(L, 1))
447                 name = lua_tostring(L, 1);
448         getServer(L)->reportPrivsModified(name);
449         return 0;
450 }
451
452 // get_last_run_mod()
453 int ModApiServer::l_get_last_run_mod(lua_State *L)
454 {
455         NO_MAP_LOCK_REQUIRED;
456         lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
457         const char *current_mod = lua_tostring(L, -1);
458         if (current_mod == NULL || current_mod[0] == '\0') {
459                 lua_pop(L, 1);
460                 lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
461         }
462         return 1;
463 }
464
465 // set_last_run_mod(modname)
466 int ModApiServer::l_set_last_run_mod(lua_State *L)
467 {
468         NO_MAP_LOCK_REQUIRED;
469 #ifdef SCRIPTAPI_DEBUG
470         const char *mod = lua_tostring(L, 1);
471         getScriptApiBase(L)->setOriginDirect(mod);
472         //printf(">>>> last mod set from Lua: %s\n", mod);
473 #endif
474         return 0;
475 }
476
477 #ifndef NDEBUG
478 // cause_error(type_of_error)
479 int ModApiServer::l_cause_error(lua_State *L)
480 {
481         NO_MAP_LOCK_REQUIRED;
482         std::string type_of_error = "none";
483         if(lua_isstring(L, 1))
484                 type_of_error = lua_tostring(L, 1);
485
486         errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
487
488         if(type_of_error == "segv") {
489                 volatile int* some_pointer = 0;
490                 errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
491
492         } else if (type_of_error == "zerodivision") {
493
494                 unsigned int some_number = porting::getTimeS();
495                 unsigned int zerovalue = 0;
496                 unsigned int result = some_number / zerovalue;
497                 errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
498
499         } else if (type_of_error == "exception") {
500                 throw BaseException("Errorhandler test fct called");
501         }
502
503         return 0;
504 }
505 #endif
506
507 void ModApiServer::Initialize(lua_State *L, int top)
508 {
509         API_FCT(request_shutdown);
510         API_FCT(get_server_status);
511         API_FCT(get_worldpath);
512         API_FCT(is_singleplayer);
513
514         API_FCT(get_current_modname);
515         API_FCT(get_modpath);
516         API_FCT(get_modnames);
517
518         API_FCT(print);
519
520         API_FCT(chat_send_all);
521         API_FCT(chat_send_player);
522         API_FCT(show_formspec);
523         API_FCT(sound_play);
524         API_FCT(sound_stop);
525
526         API_FCT(get_player_information);
527         API_FCT(get_player_privs);
528         API_FCT(get_player_ip);
529         API_FCT(get_ban_list);
530         API_FCT(get_ban_description);
531         API_FCT(ban_player);
532         API_FCT(kick_player);
533         API_FCT(unban_player_or_ip);
534         API_FCT(notify_authentication_modified);
535
536         API_FCT(get_last_run_mod);
537         API_FCT(set_last_run_mod);
538 #ifndef NDEBUG
539         API_FCT(cause_error);
540 #endif
541 }