#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); 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); IsItTimeToRestartForced(); 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) { int iPlayers = GetClientCount(false); for(int i = 1; i <= MaxClients; i++) { if(IsClientConnected(i) && IsFakeClient(i)) iPlayers--; } if((iPlayers <= 1) && IsItTimeToRestartNight()) { PrepareRestartNight(); return Plugin_Stop; } if(IsItTimeToRestartForced()) return Plugin_Stop; return Plugin_Continue; } //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- stock bool IsItTimeToRestartNight() { if (GetEngineTime() < (3600 * 12)) return false; int iTime = GetTime(); int iHour; char sTime[32]; FormatTime(sTime, sizeof(sTime), "%H", iTime); iHour = StringToInt(sTime[0]); if (iHour >= 3 && iHour < 8) return true; return false; } //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- public bool IsItTimeToRestartForced() { if(g_bRestart) return true; if(GetEngineTime() < (g_cvarMaxUptime.FloatValue * 3600.0)) return false; g_bRestart = true; NotifyAdmins(); return true; } //---------------------------------------------------------------------------------------------------- // 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 PrepareRestartNight() { NotifyAdmins(); g_fCumulativeUptime += GetEngineTime(); char sUptime[64]; FloatToString(g_fCumulativeUptime, sUptime, sizeof(sUptime)); File UptimeFile = OpenFile("uptime.txt", "w"); UptimeFile.WriteLine(sUptime); delete UptimeFile; char sMap[64]; GetCurrentMap(sMap, sizeof(sMap)); 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 night-restarted the Server."); RequestFrame(Restart); } //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- public void Restart() { ServerCommand("_restart"); } //---------------------------------------------------------------------------------------------------- // 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 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); }