AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   [TF2] Quick plugin review before I submit (https://forums.alliedmods.net/showthread.php?t=338632)

CoolJosh3k 07-18-2022 02:10

[TF2] Quick plugin review before I submit
 
Hi there, :bacon!:

I was hoping to get some eyeballs on this before I submit it for review. Hopefully there is nothing wrong with it, but I wrote it back in 2017.

The purpose of this plugin is to stop the jitter issues that a TF2 server can experience if the server has been empty and on the same map for too long.
I'm not entirely sure how to describe it, other than a server getting the jitters. If you've ever connected to a server that has been sitting on the same map for hours you'll probably know what I mean.

It is a basic solution of just restarting the server every hour, provided there is no one actually in it.

Thanks in advance to anyone who can verify it for me, or help me fix issues. :)

Here is my code:

Code:

#include <sourcemod>

new Handle:hEnable;
new Handle:hUpTime_Min, Handle:hUpTime_Max;
new Handle:hMaxPlayers;
new Handle:hWarn_ShowChat;
new bool:InRestartCountdown;
new iIdleTime;

public const Plugin:myinfo = {
        name = "Server UpTime Restarter",
        author = "CoolJosh3k",
        description = "Restarts a server after a specified uptime. Respects player counts.",
        version = "1.0.1",
}

public OnPluginStart()
{
        AutoExecConfig();
        hEnable = CreateConVar("SUR_Enable", "1", "Use this if you wish to stop plugin functions temporarily.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
        hUpTime_Min = CreateConVar("SUR_UpTime_Min", "3600", "Minimum time in seconds before restart attempt.", FCVAR_NOTIFY, true, 60.0);
        hUpTime_Max = CreateConVar("SUR_UpTime_Max", "86400", "Time in seconds before server restart is forced, regardless of player count.", FCVAR_NOTIFY, true, 60.0);
        hMaxPlayers = CreateConVar("SUR_MinPlayers", "1", "Atleast this many players will cause the restart to be delayed. Spectators are not counted.", FCVAR_NOTIFY, true, 1.0);
        hWarn_ShowChat = CreateConVar("SUR_Warn_ShowChat", "1", "Display restart warning message as a chat message.", FCVAR_NONE, true, 0.0, true, 1.0);
        CreateTimer(1.0, CheckTime, _, TIMER_REPEAT);
}

stock bool:IsValidPlayer(client)
{
        if ((client < 1) || (client > MaxClients))
        {
                return false;
        }
        if (IsClientInGame(client))
        {
                if (IsFakeClient(client))
                {
                        return false;
                }
                if (IsClientSourceTV(client) || IsClientReplay(client))
                {
                        return false;
                }
                if (GetClientTeam(client) < 2)        //No team or spectator
                {
                        return false;
                }
        }
        else        //Client is not in the game
        {
                return false;
        }
        return true;
}

public Action:CheckTime(Handle:timer)
{
        if (GetConVarBool(hEnable) == false)
        {
                return;
        }
        if (InRestartCountdown)        //We are already going to be restarting, but we are busy still letting players know before we actually do.
        {
                return;
        }
        if (GetEngineTime() >= GetConVarInt(hUpTime_Max))        //It has been far too long. A server restart must happen.
        {
                BeginServerRestart();
                return;
        }
        if (GetEngineTime() >= GetConVarInt(hUpTime_Min))
        {
                if (GetGameTime() < 60.0)        //Give time for server to fill. It only just started a new map and might have had enough players.
                {
                        iIdleTime++;        //GameTime will not start incrementing without at least 1 player, so we must account for that scenario.
                        if (iIdleTime < 60)        //We have been not been idle for long enough. Someone might be coming.
                        {
                                return;
                        }
                }
                else
                {
                        iIdleTime = 0;
                }
                new TotalActivePlayers;
                for (new client = 1; client <= MaxClients; client++)
                {
                        if (IsValidPlayer(client))
                        {
                                TotalActivePlayers++;
                        }
                }
                if (TotalActivePlayers >= GetConVarInt(hMaxPlayers))
                {
                        return;
                }
                else
                {
                        BeginServerRestart();
                        return;
                }
        }
        return;
}

public OnMapEnd()
{
        if (GetConVarBool(hEnable) == false)
        {
                return;
        }
        if (InRestartCountdown)
        {
                LogMessage("Server restart using \"Server UpTime Restarter\" on map end...");
                ServerCommand("_restart");
        }
}

//=================================//
//- Chain of timers for countdown -//


public BeginServerRestart()
{
        InRestartCountdown = true;
        if (GetConVarBool(hWarn_ShowChat))
        {
                PrintToChatAll("\x03SUR: \x04Server will perform scheduled restart in 60 seconds.");
        }
        CreateTimer(30.0, ServerRestartThirty);
}

public Action:ServerRestartThirty(Handle:timer)
{
        if (GetConVarBool(hEnable))
        {
                if (GetConVarBool(hWarn_ShowChat))
                {
                        PrintToChatAll("\x03SUR: \x04Server will perform scheduled restart in 30 seconds.");
                }
                CreateTimer(20.0, ServerRestartTen);
        }
        else
        {
                InRestartCountdown = false;
        }
}

public Action:ServerRestartTen(Handle:timer)
{
        if (GetConVarBool(hEnable))
        {
                if (GetConVarBool(hWarn_ShowChat))
                {
                        PrintToChatAll("\x03SUR: \x04Server will perform scheduled restart in TEN seconds.");
                }
                CreateTimer(5.0, ServerRestartFive);
        }
        else
        {
                InRestartCountdown = false;
        }
}

public Action:ServerRestartFive(Handle:timer)
{
        if (GetConVarBool(hEnable))
        {
                if (GetConVarBool(hWarn_ShowChat))
                {
                        PrintToChatAll("\x03SUR: \x04Server will perform scheduled restart in FIVE seconds!");
                }
                CreateTimer(4.0, ServerRestartOne);
        }
        else
        {
                InRestartCountdown = false;
        }
}

public Action:ServerRestartOne(Handle:timer)
{
        if (GetConVarBool(hEnable))
        {
                if (GetConVarBool(hWarn_ShowChat))
                {
                        PrintToChatAll("\x03SUR: \x04Server will now restart!");
                }
                CreateTimer(1.0, ServerRestartZero);
        }
        else
        {
                InRestartCountdown = false;
        }
}

public Action:ServerRestartZero(Handle:timer)
{
        if (GetConVarBool(hEnable))
        {
                LogMessage("Server restart using \"Server UpTime Restarter\"...");
                ServerCommand("_restart");
        }
        else
        {
                InRestartCountdown = false;
        }
}


Bugsy 07-18-2022 03:04

Re: [TF2] Quick plugin review before I submit
 
Moved to SM

CoolJosh3k 07-18-2022 03:51

Re: [TF2] Quick plugin review before I submit
 
Quote:

Originally Posted by Bugsy (Post 2784046)
Moved to SM

Whoops. Sorry about that.

I did not even notice I was under the AMX section due to how things are laid out.

FlaminSarge 07-19-2022 19:31

Re: [TF2] Quick plugin review before I submit
 
This jitter is probably because the server GameTime value gets very high and starts to experience floating point imprecision. This video takes it to an extreme, but it's a similar deal.
I thought that a simple mapchange fixes this, rather than a restart? I didn't think this issue affected EngineTime, either.

CoolJosh3k 07-19-2022 23:59

Re: [TF2] Quick plugin review before I submit
 
Quote:

Originally Posted by FlaminSarge (Post 2784227)
This jitter is probably because the server GameTime value gets very high and starts to experience floating point imprecision. This video takes it to an extreme, but it's a similar deal.
I thought that a simple mapchange fixes this, rather than a restart? I didn't think this issue affected EngineTime, either.

A floating point error makes perfect sense.
Of course back in 2017, when I wrote this, I probably didn't even know what a floating point was! :P

Simply changing the map is probably a better solution, but I figure a restart is going to possibly catch other issues that might also exist on a server. The one downside I can think of for a restart, is that it creates a whole new log file.

Once the basic functionality is public as an actual plugin, I'd be very welcoming if anyone wanted to update it an add the ability to initiate a map change instead. Of course this does open questions about which map and how to decide.

I would assume then that there are no obvious issues. I am inclined to submit this as an actual public-ready plugin then soon.

FlaminSarge 08-03-2022 17:11

Re: [TF2] Quick plugin review before I submit
 
Quote:

Originally Posted by CoolJosh3k (Post 2784246)
Of course this does open questions about which map and how to decide.

...The current map, maybe?

It may be worth having this plugin check GameTime/EngineTime is a very high actual value (one that would have floating point imprecision) before doing any changes. That could probably be accomplished by having the default value of each of the time cvars just be ridiculously high (ideally just before server starts getting really bad FP imprecision).

Potential concern would be whether float to int comparison (GetEngineTime() >= (cvar int value)) has trouble when either side of the comparison may be a ridiculously high value.

CoolJosh3k 08-04-2022 23:43

Re: [TF2] Quick plugin review before I submit
 
Quote:

Originally Posted by FlaminSarge (Post 2785533)
...The current map, maybe?

It may be worth having this plugin check GameTime/EngineTime is a very high actual value (one that would have floating point imprecision) before doing any changes. That could probably be accomplished by having the default value of each of the time cvars just be ridiculously high (ideally just before server starts getting really bad FP imprecision).

Potential concern would be whether float to int comparison (GetEngineTime() >= (cvar int value)) has trouble when either side of the comparison may be a ridiculously high value.

While I do assume it is floating error related (as well as others like yourself), I can't know for sure.

I expect if only ever treated as a float, then it is possible to detect when an error would have occurred. I think though that having it be some regular, predictable outcome that a server operator can configure is quite useful.

I have since released this plugin in a more official capacity, as per this thread: https://forums.alliedmods.net/showthread.php?t=338903

There are certainly a few things that could be added to make this plugin more flexible, but the base functionality and solution is all there.

It is my hope that by sharing this really old solution of mine, that others in the community might get some use out of it.

Marttt 08-05-2022 11:37

Re: [TF2] Quick plugin review before I submit
 
use new syntax: https://wiki.alliedmods.net/SourcePa...itional_Syntax

CoolJosh3k 08-06-2022 23:42

Re: [TF2] Quick plugin review before I submit
 
Quote:

Originally Posted by Marttt (Post 2785646)

If I write a plugin again, I will certainly do so. This one was originally written quite a few years ago.


All times are GMT -4. The time now is 12:18.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.