Skip to content

Commit 34d32ce

Browse files
authoredApr 15, 2017
Implement delayed server shutdown with cancelation (#4664)
1 parent 0f955bf commit 34d32ce

File tree

8 files changed

+124
-14
lines changed

8 files changed

+124
-14
lines changed
 

Diff for: ‎builtin/game/chatcommands.lua

+11-5
Original file line numberDiff line numberDiff line change
@@ -763,14 +763,20 @@ core.register_chatcommand("days", {
763763

764764
core.register_chatcommand("shutdown", {
765765
description = "Shutdown server",
766-
params = "[reconnect] [message]",
766+
params = "[delay_in_seconds(0..inf) or -1 for cancel] [reconnect] [message]",
767767
privs = {server=true},
768768
func = function(name, param)
769-
core.log("action", name .. " shuts down server")
770-
core.chat_send_all("*** Server shutting down (operator request).")
771-
local reconnect, message = param:match("([^ ]+)(.*)")
769+
local delay, reconnect, message = param:match("([^ ][-]?[0-9]+)([^ ]+)(.*)")
772770
message = message or ""
773-
core.request_shutdown(message:trim(), core.is_yes(reconnect))
771+
772+
if delay ~= "" then
773+
delay = tonumber(param) or 0
774+
else
775+
delay = 0
776+
core.log("action", name .. " shuts down server")
777+
core.chat_send_all("*** Server shutting down (operator request).")
778+
end
779+
core.request_shutdown(message:trim(), core.is_yes(reconnect), delay)
774780
end,
775781
})
776782

Diff for: ‎builtin/game/misc.lua

+5
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,8 @@ end
173173
function core.close_formspec(player_name, formname)
174174
return minetest.show_formspec(player_name, formname, "")
175175
end
176+
177+
function core.cancel_shutdown_requests()
178+
core.request_shutdown("", false, -1)
179+
end
180+

Diff for: ‎doc/lua_api.txt

+6-2
Original file line numberDiff line numberDiff line change
@@ -2576,8 +2576,12 @@ These functions return the leftover itemstack.
25762576
* Optional: Variable number of arguments that are passed to `func`
25772577

25782578
### Server
2579-
* `minetest.request_shutdown([message],[reconnect])`: request for server shutdown. Will display `message` to clients,
2580-
and `reconnect` == true displays a reconnect button.
2579+
* `minetest.request_shutdown([message],[reconnect],[delay])`: request for server shutdown. Will display `message` to clients,
2580+
`reconnect` == true displays a reconnect button,
2581+
`delay` adds an optional delay (in seconds) before shutdown
2582+
negative delay cancels the current active shutdown
2583+
zero delay triggers an immediate shutdown.
2584+
* `minetest.cancel_shutdown_requests()`: cancel current delayed shutdown
25812585
* `minetest.get_server_status()`: returns server status string
25822586
* `minetest.get_server_uptime()`: returns the server uptime in seconds
25832587

Diff for: ‎src/network/serverpackethandler.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,13 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
722722

723723
m_clients.event(peer_id, CSE_SetClientReady);
724724
m_script->on_joinplayer(playersao);
725+
// Send shutdown timer if shutdown has been scheduled
726+
if (m_shutdown_timer > 0.0f) {
727+
std::wstringstream ws;
728+
ws << L"*** Server shutting down in "
729+
<< duration_to_string(round(m_shutdown_timer)).c_str() << ".";
730+
SendChatMessage(pkt->getPeerId(), ws.str());
731+
}
725732
}
726733

727734
void Server::handleCommand_GotBlocks(NetworkPacket* pkt)

Diff for: ‎src/script/lua_api/l_server.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ int ModApiServer::l_request_shutdown(lua_State *L)
3333
NO_MAP_LOCK_REQUIRED;
3434
const char *msg = lua_tolstring(L, 1, NULL);
3535
bool reconnect = lua_toboolean(L, 2);
36-
getServer(L)->requestShutdown(msg ? msg : "", reconnect);
36+
float seconds_before_shutdown = lua_tonumber(L, 3);
37+
getServer(L)->requestShutdown(msg ? msg : "", reconnect, seconds_before_shutdown);
3738
return 0;
3839
}
3940

Diff for: ‎src/server.cpp

+67
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ Server::Server(
177177
m_clients(&m_con),
178178
m_shutdown_requested(false),
179179
m_shutdown_ask_reconnect(false),
180+
m_shutdown_timer(0.0f),
180181
m_admin_chat(iface),
181182
m_ignore_map_edit_events(false),
182183
m_ignore_map_edit_events_peer_id(0),
@@ -1029,6 +1030,39 @@ void Server::AsyncRunStep(bool initial_step)
10291030
m_env->saveMeta();
10301031
}
10311032
}
1033+
1034+
// Timed shutdown
1035+
static const float shutdown_msg_times[] =
1036+
{
1037+
1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 45, 60, 120, 180, 300, 600, 1200, 1800, 3600
1038+
};
1039+
1040+
if (m_shutdown_timer > 0.0f) {
1041+
// Automated messages
1042+
if (m_shutdown_timer < shutdown_msg_times[ARRLEN(shutdown_msg_times) - 1]) {
1043+
for (u16 i = 0; i < ARRLEN(shutdown_msg_times) - 1; i++) {
1044+
// If shutdown timer matches an automessage, shot it
1045+
if (m_shutdown_timer > shutdown_msg_times[i] &&
1046+
m_shutdown_timer - dtime < shutdown_msg_times[i]) {
1047+
std::wstringstream ws;
1048+
1049+
ws << L"*** Server shutting down in "
1050+
<< duration_to_string(round(m_shutdown_timer - dtime)).c_str()
Has a comment. Original line has a comment.
1051+
<< ".";
1052+
1053+
infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
1054+
SendChatMessage(PEER_ID_INEXISTENT, ws.str());
1055+
break;
1056+
}
1057+
}
1058+
}
1059+
1060+
m_shutdown_timer -= dtime;
1061+
if (m_shutdown_timer < 0.0f) {
1062+
m_shutdown_timer = 0.0f;
1063+
m_shutdown_requested = true;
1064+
}
1065+
}
10321066
}
10331067

10341068
void Server::Receive()
@@ -3443,6 +3477,39 @@ v3f Server::findSpawnPos()
34433477
return nodeposf;
34443478
}
34453479

3480+
void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3481+
{
3482+
if (delay == 0.0f) {
3483+
// No delay, shutdown immediately
3484+
m_shutdown_requested = true;
3485+
} else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3486+
// Negative delay, cancel shutdown if requested
3487+
m_shutdown_timer = 0.0f;
3488+
m_shutdown_msg = "";
3489+
m_shutdown_ask_reconnect = false;
3490+
m_shutdown_requested = false;
3491+
std::wstringstream ws;
3492+
3493+
ws << L"*** Server shutdown canceled.";
3494+
3495+
infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3496+
SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3497+
} else if (delay > 0.0f) {
3498+
// Positive delay, delay the shutdown
3499+
m_shutdown_timer = delay;
3500+
m_shutdown_msg = msg;
3501+
m_shutdown_ask_reconnect = reconnect;
3502+
std::wstringstream ws;
3503+
3504+
ws << L"*** Server shutting down in "
3505+
<< duration_to_string(round(m_shutdown_timer)).c_str()
Has a comment. Original line has a comment.
3506+
<< ".";
3507+
3508+
infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3509+
SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3510+
}
3511+
}
3512+
34463513
PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
34473514
{
34483515
bool newplayer = false;

Diff for: ‎src/server.h

+2-6
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
226226
inline bool getShutdownRequested() const { return m_shutdown_requested; }
227227

228228
// request server to shutdown
229-
void requestShutdown(const std::string &msg, bool reconnect)
230-
{
231-
m_shutdown_requested = true;
232-
m_shutdown_msg = msg;
233-
m_shutdown_ask_reconnect = reconnect;
234-
}
229+
void requestShutdown(const std::string &msg, bool reconnect, float delay = 0.0f);
235230

236231
// Returns -1 if failed, sound handle on success
237232
// Envlock
@@ -602,6 +597,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
602597
bool m_shutdown_requested;
603598
std::string m_shutdown_msg;
604599
bool m_shutdown_ask_reconnect;
600+
float m_shutdown_timer;
605601

606602
ChatInterface *m_admin_chat;
607603
std::string m_admin_nick;

Diff for: ‎src/util/string.h

+24
Original file line numberDiff line numberDiff line change
@@ -614,4 +614,28 @@ inline const char *bool_to_cstr(bool val)
614614
return val ? "true" : "false";
615615
}
616616

617+
inline const std::string duration_to_string(int sec)
618+
{
619+
int min = floor(sec / 60);
620+
sec %= 60;
621+
int hour = floor(min / 60);
Has a comment. Original line has a comment.
622+
min %= 60;
623+
624+
std::stringstream ss;
625+
if (hour > 0) {
626+
ss << hour << "h ";
627+
}
628+
629+
if (min > 0) {
630+
ss << min << "m ";
631+
}
632+
633+
if (sec > 0) {
634+
ss << sec << "s ";
635+
}
636+
637+
return ss.str();
638+
}
639+
640+
617641
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.