diff --git a/RestartManager/scripting/RestartManager.sp b/RestartManager/scripting/RestartManager.sp new file mode 100644 index 00000000..db90e075 --- /dev/null +++ b/RestartManager/scripting/RestartManager.sp @@ -0,0 +1,243 @@ +#include +#include +#include + +#pragma semicolon 1 +#pragma newdecls required + +float g_fCumulativeUptime; + +bool g_bRestart; + +ConVar g_cvarDefaultMap; +ConVar g_cvarMaxUptime; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "RestartManager", + author = "Dogan + Neon", + description = "Display Server Uptime and do controlled Restarts", + version = "1.0.0", + url = "" +}; +// TODO: SAFE command for admins to restart!!! +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + RegAdminCmd("uptime", Command_Uptime, ADMFLAG_GENERIC, "Displays server Uptime"); + RegAdminCmd("sm_uptime", Command_Uptime, ADMFLAG_GENERIC, "Displays server Uptime"); + + g_cvarDefaultMap = CreateConVar("sm_defaultmap", "ze_atix_panic_b3t", "default map of the server"); + g_cvarMaxUptime = CreateConVar("sm_maxuptime", "68", "Uptime in hours after which the server should be restarted", FCVAR_NONE); + AutoExecConfig(true); + + GetUptimeIfControlledRestart(); + char sDefaultMap[64]; + g_cvarDefaultMap.GetString(sDefaultMap, sizeof(sDefaultMap)); + SetStartMap(sDefaultMap); + + RegServerCmd("changelevel", BlockMapSwitch); + + IsItTimeToRestart(); + CreateTimer(60.0, CheckForRestart, _, TIMER_REPEAT); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_Uptime(int client, int args) +{ + float fUptime = GetEngineTime(); + char sUptime[64]; + int iUptime = RoundFloat(fUptime); + + int iDays = (iUptime / 86400); + int iHours = (iUptime / 3600) % 24; + int iMinutes = (iUptime / 60) % 60; + int iSeconds = (iUptime % 60); + + if (iDays) + Format(sUptime, sizeof(sUptime), "%d Days %d Hours %d Minutes %d Seconds.", iDays, iHours, iMinutes, iSeconds); + else if (iHours) + Format(sUptime, sizeof(sUptime), "%d Hours %d Minutes %d Seconds.", iHours, iMinutes, iSeconds); + else if (iMinutes) + Format(sUptime, sizeof(sUptime), "%d Minutes %d Seconds.", iMinutes, iSeconds); + else + Format(sUptime, sizeof(sUptime), "%d Seconds.", iSeconds); + + ReplyToCommand(client, "[SM] Real Server Uptime: %s", sUptime); + + fUptime = GetEngineTime() + g_fCumulativeUptime; + iUptime = RoundFloat(fUptime); + + iDays = (iUptime / 86400); + iHours = (iUptime / 3600) % 24; + iMinutes = (iUptime / 60) % 60; + iSeconds = (iUptime % 60); + + if (iDays) + Format(sUptime, sizeof(sUptime), "%d Days %d Hours %d Minutes %d Seconds.", iDays, iHours, iMinutes, iSeconds); + else if (iHours) + Format(sUptime, sizeof(sUptime), "%d Hours %d Minutes %d Seconds.", iHours, iMinutes, iSeconds); + else if (iMinutes) + Format(sUptime, sizeof(sUptime), "%d Minutes %d Seconds.", iMinutes, iSeconds); + else + Format(sUptime, sizeof(sUptime), "%d Seconds.", iSeconds); + + ReplyToCommand(client, "[SM] Cumulative Server Uptime: %s", sUptime); + + IsItTimeToRestart(); + if (g_bRestart) + ReplyToCommand(client, "[SM] Server is going to restart on next mapswitch"); + else + ReplyToCommand(client, "[SM] Time until next restart: %.2fh", ((g_cvarMaxUptime.FloatValue * 3600.0) - GetEngineTime()) / 3600.0); + + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action CheckForRestart(Handle timer) +{ + if(!IsItTimeToRestart()) + return Plugin_Continue; + + return Plugin_Stop; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public bool IsItTimeToRestart() +{ + if(g_bRestart) + return true; + + if(GetEngineTime() < (g_cvarMaxUptime.FloatValue * 3600.0)) + return false; + + g_bRestart = true; + NotifyAdmins(); + return true; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action BlockMapSwitch(int args) +{ + if (!g_bRestart) + return Plugin_Continue; + + char sMap[64]; + GetCmdArg(1, sMap, sizeof(sMap)); + PrepareRestart(sMap); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void PrepareRestart(char[] sMap) +{ + NotifyAdmins(); + + g_fCumulativeUptime += GetEngineTime(); + + char sUptime[64]; + FloatToString(g_fCumulativeUptime, sUptime, sizeof(sUptime)); + File UptimeFile = OpenFile("uptime.txt", "w"); + UptimeFile.WriteLine(sUptime); + delete UptimeFile; + + if(sMap[0]) + { + char sMapFile[68]; + Format(sMapFile, sizeof(sMapFile), "map %s", sMap); + DeleteFile("cfg/defaultmap.cfg"); + File NextmapFile = OpenFile("cfg/defaultmap.cfg", "w"); + NextmapFile.WriteLine(sMapFile); + delete NextmapFile; + } + + SimulateMapEnd(); + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientConnected(i) && !IsFakeClient(i)) + ClientCommand(i, "retry"); + } + LogToFile("addons/sourcemod/logs/restarts.log", "Successfully force-restarted the Server."); + RequestFrame(Restart); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void Restart() +{ + ServerCommand("_restart"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void GetUptimeIfControlledRestart() +{ + File UptimeFile = OpenFile("uptime.txt", "r"); + + if(UptimeFile != null)//Server was restarted automatically by this plugin + { + char sUptime[64]; + UptimeFile.ReadLine(sUptime, sizeof(sUptime)); + g_fCumulativeUptime = StringToFloat(sUptime); + delete UptimeFile; + DeleteFile("uptime.txt"); + } + else//Server crashed or restarted manually + LogToFile("addons/sourcemod/logs/restarts.log", "Server crashed or was restarted manually."); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void SetStartMap(char[] sMap) +{ + DeleteFile("cfg/defaultmap.cfg"); + char sMapFile[64]; + Format(sMapFile, sizeof(sMapFile), "map %s", sMap); + File NextmapFile = OpenFile("cfg/defaultmap.cfg", "w"); + NextmapFile.WriteLine(sMapFile); + delete NextmapFile; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void NotifyAdmins() +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsValidClient(i) && CheckCommandAccess(i, "", ADMFLAG_KICK)) + { + PrintToChat(i, "[SM] WARNING: Server will be restarted on mapswitch!"); + PrintToChat(i, "[SM] WARNING: Server will be restarted on mapswitch!"); + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock int IsValidClient(int client, bool nobots = true) +{ + if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (nobots && IsFakeClient(client))) + return false; + + return IsClientInGame(client); +}