forked from Mirrorlandia_minetest/minetest
Implement delayed server shutdown with cancelation (#4664)
This commit is contained in:
parent
0f955bf7fa
commit
34d32ce55a
@ -763,14 +763,20 @@ core.register_chatcommand("days", {
|
|||||||
|
|
||||||
core.register_chatcommand("shutdown", {
|
core.register_chatcommand("shutdown", {
|
||||||
description = "Shutdown server",
|
description = "Shutdown server",
|
||||||
params = "[reconnect] [message]",
|
params = "[delay_in_seconds(0..inf) or -1 for cancel] [reconnect] [message]",
|
||||||
privs = {server=true},
|
privs = {server=true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
|
local delay, reconnect, message = param:match("([^ ][-]?[0-9]+)([^ ]+)(.*)")
|
||||||
|
message = message or ""
|
||||||
|
|
||||||
|
if delay ~= "" then
|
||||||
|
delay = tonumber(param) or 0
|
||||||
|
else
|
||||||
|
delay = 0
|
||||||
core.log("action", name .. " shuts down server")
|
core.log("action", name .. " shuts down server")
|
||||||
core.chat_send_all("*** Server shutting down (operator request).")
|
core.chat_send_all("*** Server shutting down (operator request).")
|
||||||
local reconnect, message = param:match("([^ ]+)(.*)")
|
end
|
||||||
message = message or ""
|
core.request_shutdown(message:trim(), core.is_yes(reconnect), delay)
|
||||||
core.request_shutdown(message:trim(), core.is_yes(reconnect))
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -173,3 +173,8 @@ end
|
|||||||
function core.close_formspec(player_name, formname)
|
function core.close_formspec(player_name, formname)
|
||||||
return minetest.show_formspec(player_name, formname, "")
|
return minetest.show_formspec(player_name, formname, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function core.cancel_shutdown_requests()
|
||||||
|
core.request_shutdown("", false, -1)
|
||||||
|
end
|
||||||
|
|
||||||
|
@ -2576,8 +2576,12 @@ These functions return the leftover itemstack.
|
|||||||
* Optional: Variable number of arguments that are passed to `func`
|
* Optional: Variable number of arguments that are passed to `func`
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
* `minetest.request_shutdown([message],[reconnect])`: request for server shutdown. Will display `message` to clients,
|
* `minetest.request_shutdown([message],[reconnect],[delay])`: request for server shutdown. Will display `message` to clients,
|
||||||
and `reconnect` == true displays a reconnect button.
|
`reconnect` == true displays a reconnect button,
|
||||||
|
`delay` adds an optional delay (in seconds) before shutdown
|
||||||
|
negative delay cancels the current active shutdown
|
||||||
|
zero delay triggers an immediate shutdown.
|
||||||
|
* `minetest.cancel_shutdown_requests()`: cancel current delayed shutdown
|
||||||
* `minetest.get_server_status()`: returns server status string
|
* `minetest.get_server_status()`: returns server status string
|
||||||
* `minetest.get_server_uptime()`: returns the server uptime in seconds
|
* `minetest.get_server_uptime()`: returns the server uptime in seconds
|
||||||
|
|
||||||
|
@ -722,6 +722,13 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
|
|||||||
|
|
||||||
m_clients.event(peer_id, CSE_SetClientReady);
|
m_clients.event(peer_id, CSE_SetClientReady);
|
||||||
m_script->on_joinplayer(playersao);
|
m_script->on_joinplayer(playersao);
|
||||||
|
// Send shutdown timer if shutdown has been scheduled
|
||||||
|
if (m_shutdown_timer > 0.0f) {
|
||||||
|
std::wstringstream ws;
|
||||||
|
ws << L"*** Server shutting down in "
|
||||||
|
<< duration_to_string(round(m_shutdown_timer)).c_str() << ".";
|
||||||
|
SendChatMessage(pkt->getPeerId(), ws.str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handleCommand_GotBlocks(NetworkPacket* pkt)
|
void Server::handleCommand_GotBlocks(NetworkPacket* pkt)
|
||||||
|
@ -33,7 +33,8 @@ int ModApiServer::l_request_shutdown(lua_State *L)
|
|||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
const char *msg = lua_tolstring(L, 1, NULL);
|
const char *msg = lua_tolstring(L, 1, NULL);
|
||||||
bool reconnect = lua_toboolean(L, 2);
|
bool reconnect = lua_toboolean(L, 2);
|
||||||
getServer(L)->requestShutdown(msg ? msg : "", reconnect);
|
float seconds_before_shutdown = lua_tonumber(L, 3);
|
||||||
|
getServer(L)->requestShutdown(msg ? msg : "", reconnect, seconds_before_shutdown);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +177,7 @@ Server::Server(
|
|||||||
m_clients(&m_con),
|
m_clients(&m_con),
|
||||||
m_shutdown_requested(false),
|
m_shutdown_requested(false),
|
||||||
m_shutdown_ask_reconnect(false),
|
m_shutdown_ask_reconnect(false),
|
||||||
|
m_shutdown_timer(0.0f),
|
||||||
m_admin_chat(iface),
|
m_admin_chat(iface),
|
||||||
m_ignore_map_edit_events(false),
|
m_ignore_map_edit_events(false),
|
||||||
m_ignore_map_edit_events_peer_id(0),
|
m_ignore_map_edit_events_peer_id(0),
|
||||||
@ -1029,6 +1030,39 @@ void Server::AsyncRunStep(bool initial_step)
|
|||||||
m_env->saveMeta();
|
m_env->saveMeta();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Timed shutdown
|
||||||
|
static const float shutdown_msg_times[] =
|
||||||
|
{
|
||||||
|
1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 45, 60, 120, 180, 300, 600, 1200, 1800, 3600
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_shutdown_timer > 0.0f) {
|
||||||
|
// Automated messages
|
||||||
|
if (m_shutdown_timer < shutdown_msg_times[ARRLEN(shutdown_msg_times) - 1]) {
|
||||||
|
for (u16 i = 0; i < ARRLEN(shutdown_msg_times) - 1; i++) {
|
||||||
|
// If shutdown timer matches an automessage, shot it
|
||||||
|
if (m_shutdown_timer > shutdown_msg_times[i] &&
|
||||||
|
m_shutdown_timer - dtime < shutdown_msg_times[i]) {
|
||||||
|
std::wstringstream ws;
|
||||||
|
|
||||||
|
ws << L"*** Server shutting down in "
|
||||||
|
<< duration_to_string(round(m_shutdown_timer - dtime)).c_str()
|
||||||
|
<< ".";
|
||||||
|
|
||||||
|
infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
|
||||||
|
SendChatMessage(PEER_ID_INEXISTENT, ws.str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shutdown_timer -= dtime;
|
||||||
|
if (m_shutdown_timer < 0.0f) {
|
||||||
|
m_shutdown_timer = 0.0f;
|
||||||
|
m_shutdown_requested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::Receive()
|
void Server::Receive()
|
||||||
@ -3443,6 +3477,39 @@ v3f Server::findSpawnPos()
|
|||||||
return nodeposf;
|
return nodeposf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
|
||||||
|
{
|
||||||
|
if (delay == 0.0f) {
|
||||||
|
// No delay, shutdown immediately
|
||||||
|
m_shutdown_requested = true;
|
||||||
|
} else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
|
||||||
|
// Negative delay, cancel shutdown if requested
|
||||||
|
m_shutdown_timer = 0.0f;
|
||||||
|
m_shutdown_msg = "";
|
||||||
|
m_shutdown_ask_reconnect = false;
|
||||||
|
m_shutdown_requested = false;
|
||||||
|
std::wstringstream ws;
|
||||||
|
|
||||||
|
ws << L"*** Server shutdown canceled.";
|
||||||
|
|
||||||
|
infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
|
||||||
|
SendChatMessage(PEER_ID_INEXISTENT, ws.str());
|
||||||
|
} else if (delay > 0.0f) {
|
||||||
|
// Positive delay, delay the shutdown
|
||||||
|
m_shutdown_timer = delay;
|
||||||
|
m_shutdown_msg = msg;
|
||||||
|
m_shutdown_ask_reconnect = reconnect;
|
||||||
|
std::wstringstream ws;
|
||||||
|
|
||||||
|
ws << L"*** Server shutting down in "
|
||||||
|
<< duration_to_string(round(m_shutdown_timer)).c_str()
|
||||||
|
<< ".";
|
||||||
|
|
||||||
|
infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
|
||||||
|
SendChatMessage(PEER_ID_INEXISTENT, ws.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
|
PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
|
||||||
{
|
{
|
||||||
bool newplayer = false;
|
bool newplayer = false;
|
||||||
|
@ -226,12 +226,7 @@ public:
|
|||||||
inline bool getShutdownRequested() const { return m_shutdown_requested; }
|
inline bool getShutdownRequested() const { return m_shutdown_requested; }
|
||||||
|
|
||||||
// request server to shutdown
|
// request server to shutdown
|
||||||
void requestShutdown(const std::string &msg, bool reconnect)
|
void requestShutdown(const std::string &msg, bool reconnect, float delay = 0.0f);
|
||||||
{
|
|
||||||
m_shutdown_requested = true;
|
|
||||||
m_shutdown_msg = msg;
|
|
||||||
m_shutdown_ask_reconnect = reconnect;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns -1 if failed, sound handle on success
|
// Returns -1 if failed, sound handle on success
|
||||||
// Envlock
|
// Envlock
|
||||||
@ -602,6 +597,7 @@ private:
|
|||||||
bool m_shutdown_requested;
|
bool m_shutdown_requested;
|
||||||
std::string m_shutdown_msg;
|
std::string m_shutdown_msg;
|
||||||
bool m_shutdown_ask_reconnect;
|
bool m_shutdown_ask_reconnect;
|
||||||
|
float m_shutdown_timer;
|
||||||
|
|
||||||
ChatInterface *m_admin_chat;
|
ChatInterface *m_admin_chat;
|
||||||
std::string m_admin_nick;
|
std::string m_admin_nick;
|
||||||
|
@ -614,4 +614,28 @@ inline const char *bool_to_cstr(bool val)
|
|||||||
return val ? "true" : "false";
|
return val ? "true" : "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const std::string duration_to_string(int sec)
|
||||||
|
{
|
||||||
|
int min = floor(sec / 60);
|
||||||
|
sec %= 60;
|
||||||
|
int hour = floor(min / 60);
|
||||||
|
min %= 60;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
if (hour > 0) {
|
||||||
|
ss << hour << "h ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min > 0) {
|
||||||
|
ss << min << "m ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sec > 0) {
|
||||||
|
ss << sec << "s ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user