Raised This Month: $ Target: $400
 0% 

[TF2] Restart Server If No Human Clients Connected


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Tranced
Member
Join Date: Dec 2011
Location: United States
Old 04-08-2016 , 17:12   [TF2] Restart Server If No Human Clients Connected
Reply With Quote #1

Hello, I was wondering if someone could make a TF2 plugin that restarts your server if no real clients have connected for 20 minutes. This is just something I'd like to have for late nights and early mornings. I've tried to search for a plugin like this, but have not found one that does exactly this. So lets say 12 bots are connected and no one has joined for 20 minutes, the server will restart. If any amount of human players are connected the server will not restart regardless if the 20 minutes have passed.

Thank you for reading.
Tranced is offline
nosoop
Veteran Member
Join Date: Aug 2014
Old 04-09-2016 , 09:13   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #2

Here's a quick one (untested):

Code:
#include <sourcemod>

Handle g_RestartTimer;

#define SECONDS_TO_RESTART 1.0 * 60 * 20

public void OnPluginStart() {
    HookEvent("player_connect", OnPlayerConnect);
    HookEvent("player_disconnect", OnPlayerDisconnect);
}

// If the last human player disconnects, then set a 20 minute timer until it restarts.
public void OnPlayerDisconnect(Event event, const char[] name, bool dontBroadcast) {
    // If you want to add any time-related checks (e.g., for the late nights and early mornings), you could just stick them in here and return if you don't want to start a new timer.
    
    bool bDisconnectingHuman = event.GetInt("bot") == 0;
    
    if (bDisconnectingHuman) {
        bool bAnyHumanConnected = false;
        for (int i = MaxClients + 1; i > 0; --i) {
            bAnyHumanConnected |= (IsClientConnected(i) && !IsFakeClient(i));
        }
        
        if (!bAnyHumanConnected) {
            g_RestartTimer = CreateTimer(SECONDS_TO_RESTART, OnServerEmptyTooLong);
        }
    }
}

// If a human player connects, kill an existing restart timer if possible.
public void OnPlayerConnect(Event event, const char[] name, bool dontBroadcast) {
    bool bConnectingHuman = event.GetInt("bot") == 0;
    if (bConnectingHuman) {
        if (g_RestartTimer != null) {
            delete g_RestartTimer;
        }
    }
}

// Server has not killed the timer that was set 20 minutes ago.  Time to restart.
public Action OnServerEmptyTooLong(Handle timer, any data) {
    LogMessage("Server has been empty for %f seconds.  Restarting.", SECONDS_TO_RESTART);
    ServerCommand("quit"); // I assume you have your server configured to restart on shutdown.
}
Curious about your particular requirements, though.

Edit: This only restarts the server 20 minutes after the last human player leaves. If there weren't any human players to begin with, then it won't do anything.
__________________
I do TF2, TF2 servers, and TF2 plugins.
I don't do DMs over Discord -- PM me on the forums regarding inquiries.
AlliedModders Releases / Github / TF2 Server / Donate (BTC / BCH / coffee)

Last edited by nosoop; 04-09-2016 at 09:15.
nosoop is offline
Tranced
Member
Join Date: Dec 2011
Location: United States
Old 04-09-2016 , 16:00   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #3

Thank you for taking the time to do this! I will test this out shortly.

Quote:
Curious about your particular requirements, though.
What is it that you need me to be more specific about? I will gladly answer, however it seems you've included everything in the plugin that I requested

Quote:
Edit: This only restarts the server 20 minutes after the last human player leaves. If there weren't any human players to begin with, then it won't do anything.
Is there a way you could add to this plugin that if there are only bots in the server as well to do a restart? I believe that is what I was trying to get at. My idea was to get a continuous loop of restarts until actual players join the server within the 20 minute period. I like that you added a kill to the timer when a client connects.

Last edited by Tranced; 04-09-2016 at 16:04.
Tranced is offline
nosoop
Veteran Member
Join Date: Aug 2014
Old 04-10-2016 , 19:29   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #4

Quote:
Originally Posted by Tranced View Post
What is it that you need me to be more specific about? I will gladly answer, however it seems you've included everything in the plugin that I requested
Mainly curious about what kinds of maps / bots you're running, so I know if I can use round start events / global map forwards for various checks.

I have a somewhat similar personal plugin that checks if the server's been up for a long enough time and restarts during OnMapEnd() to clean up memory leaks (pretty sure they're not handle leaks). My server runs non-idle bots that can play maps to completion, so it happens to work for my setup.

Quote:
Originally Posted by Tranced View Post
Is there a way you could add to this plugin that if there are only bots in the server as well to do a restart? I believe that is what I was trying to get at. My idea was to get a continuous loop of restarts until actual players join the server within the 20 minute period. I like that you added a kill to the timer when a client connects.
Going to need confirmation on this; do you want to check if these requirements are met?
  • No human players. Last disconnecting human starts a timer.
  • Bots must be on the server.
    • If there are no bots, then the timer won't run.
  • If bots are on the server at some point during the map, maybe run the plugin.
    • (This is more of an implementation thing: Once the first bot joins, we can check if no humans are playing and start a timer.)
__________________
I do TF2, TF2 servers, and TF2 plugins.
I don't do DMs over Discord -- PM me on the forums regarding inquiries.
AlliedModders Releases / Github / TF2 Server / Donate (BTC / BCH / coffee)
nosoop is offline
Bacardi
Veteran Member
Join Date: Jan 2010
Location: mom's basement
Old 04-10-2016 , 23:45   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #5

PHP Code:

public OnPluginStart()
{
    
CreateTimer(60.0timer_repeat_TIMER_REPEAT);
}

public 
Action:timer_repeat(Handle:timer)
{
    new 
String:buffer[4], hours;

    
FormatTime(buffersizeof(buffer), "%H");
    
hours StringToInt(buffer);

    
PrintToServer("hours %i"hours)

    
// work only between 3 AM - 6 AM
    
if( !(<= hours <= 6) ) return Plugin_Continue;


    static 
minutes;

    
minutes++;

    for(new 
1<= MaxClientsi++)
    {
        if(
IsClientInGame(i) && !IsFakeClient(i)) minutes 0;
    }

    if(
minutes >= 20)
    {
        
LogAction(0, -1"Server idle for 20 minutes, shutting down");
        
ServerCommand("quit");
    }

    return 
Plugin_Continue;

__________________
Do not Private Message @me

Last edited by Bacardi; 04-11-2016 at 06:36.
Bacardi is offline
Tranced
Member
Join Date: Dec 2011
Location: United States
Old 04-11-2016 , 03:08   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #6

Quote:
Mainly curious about what kinds of maps / bots you're running, so I know if I can use round start events / global map forwards for various checks.
I run 24/7 Maps, currently I run: 2FORT, Hightower, Dustbowl, Snowycoast, 2 Landfall Maps, and I use Valves official bots with Dr. Mackay's Bot Manager plugin.
Quote:
Going to need confirmation on this; do you want to check if these requirements are met?
No human players. Last disconnecting human starts a timer.
Bots must be on the server.
If there are no bots, then the timer won't run.
If bots are on the server at some point during the map, maybe run the plugin.
(This is more of an implementation thing: Once the first bot joins, we can check if no humans are playing and start a timer.)
This is absolutely correct. To add to that, if only bots are playing, lets say its early in the morning or late at night and a late night human joins, the timer would need to be killed, but I believe you have that added already

Also thank you for making that Bacardi! I'm going to run more tests tomorrow evening.
Tranced is offline
Bacardi
Veteran Member
Join Date: Jan 2010
Location: mom's basement
Old 04-11-2016 , 06:37   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #7

...updated my post. Added time of the day it should start work.
Between 3AM - 6AM, and it still shutdown server in multiple times on that time.
*edit
make sure your srcds not hibernate, otherwise timers stop working
__________________
Do not Private Message @me

Last edited by Bacardi; 04-11-2016 at 06:57.
Bacardi is offline
Tranced
Member
Join Date: Dec 2011
Location: United States
Old 04-11-2016 , 13:58   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #8

Quote:
Originally Posted by Bacardi View Post
...updated my post. Added time of the day it should start work.
Between 3AM - 6AM, and it still shutdown server in multiple times on that time.
*edit
make sure your srcds not hibernate, otherwise timers stop working
Thank you Bacardi! Will do. What I'll do is just set it to check all hours of the day.

Last edited by Tranced; 04-12-2016 at 20:40.
Tranced is offline
Tranced
Member
Join Date: Dec 2011
Location: United States
Old 04-12-2016 , 20:35   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #9

Quote:
Going to need confirmation on this; do you want to check if these requirements are met?
No human players. Last disconnecting human starts a timer.
Bots must be on the server.
If there are no bots, then the timer won't run.
If bots are on the server at some point during the map, maybe run the plugin.
(This is more of an implementation thing: Once the first bot joins, we can check if no humans are playing and start a timer.)
Hello nosoop, I tested your plugin today and I could not get it to work properly. I even tried lowering the time to about 5 minutes, recompiled and was unable to get a server restart. Additionally, I joined my server, left for the timer to begin and did not see one restart. I tried multiple times to try and get this to work. I checked my sourcemod error logs and I saw this:

Quote:
L 04/12/2016 - 19:26:42: SourceMod error session started
L 04/12/2016 - 19:26:42: Info (map "cp_dustbowl") (file "errors_20160412.log")
L 04/12/2016 - 19:26:42: [SM] Native "IsClientConnected" reported: Client index 25 is invalid
L 04/12/2016 - 19:26:42: [SM] Displaying call stack trace for plugin "emptyserver.smx":
L 04/12/2016 - 19:26:42: [SM] [0] Line 30, /home/groups/sourcemod/upload_tmp/phpSdGumM.sp::OnPlayerDisconnect()
L 04/12/2016 - 19:27:18: [SM] Native "IsClientConnected" reported: Client index 25 is invalid
L 04/12/2016 - 19:27:18: [SM] Displaying call stack trace for plugin "emptyserver.smx":
L 04/12/2016 - 19:27:18: [SM] [0] Line 30, /home/groups/sourcemod/upload_tmp/phpSdGumM.sp::OnPlayerDisconnect()
L 04/12/2016 - 19:28:06: [SM] Native "IsClientConnected" reported: Client index 25 is invalid
L 04/12/2016 - 19:28:06: [SM] Displaying call stack trace for plugin "emptyserver.smx":
L 04/12/2016 - 19:28:06: [SM] [0] Line 30, /home/groups/sourcemod/upload_tmp/phpSdGumM.sp::OnPlayerDisconnect()
Tranced is offline
nosoop
Veteran Member
Join Date: Aug 2014
Old 04-13-2016 , 05:56   Re: [TF2] Restart Server If No Human Clients Connected
Reply With Quote #10

Quote:
Originally Posted by Tranced View Post
Hello nosoop, I tested your plugin today and I could not get it to work properly.
Wasn't sure how MaxClients was iterated, so I'm assuming it shouldn't be MaxClients + 1.

Here's a likely working plugin with some actual testing.

Code:
#include <sourcemod>

Handle g_RestartTimer;

#define SECONDS_TO_RESTART 1.0 * 60 * 20
// #define SECONDS_TO_RESTART 1.0 * 60 * 1

public void OnPluginStart() {
    HookEvent("player_connect", OnPlayerConnect);
    HookEvent("player_disconnect", OnPlayerDisconnect);
}

// If the last human player disconnects, then set a 20 minute timer until it restarts.
public void OnPlayerDisconnect(Event event, const char[] name, bool dontBroadcast) {
    bool bDisconnectingHuman = event.GetInt("bot") == 0;
    
    if (bDisconnectingHuman) {
        bool bAnyHumanConnected = false;
        bool bAnyBotsConnected = false;
        
        int disconnectingClient = GetClientOfUserId(event.GetInt("userid"));
        for (int i = MaxClients; i > 0; --i) {
            if (i == disconnectingClient) {
                continue;
            }
            
            bAnyHumanConnected |= (IsClientConnected(i) && !IsFakeClient(i));
            
            // Could always change the checks as necessary, depending on the bot.
            bAnyBotsConnected |= (IsClientConnected(i) && IsFakeClient(i)
                    && IsPlayingBot(i));
        }
        
        PrintToServer("Human %d disconnected, state %b / %b", disconnectingClient, bAnyHumanConnected, bAnyBotsConnected);
        
        if (!bAnyHumanConnected && RestartTimerEnabled()) {
            g_RestartTimer = CreateTimer(SECONDS_TO_RESTART, OnServerEmptyTooLong);
            LogMessage("Server is empty and bots are available.  Starting timer for %f seconds.", SECONDS_TO_RESTART);
        }
    }
}

// If a human player connects, kill an existing restart timer if possible.
public void OnPlayerConnect(Event event, const char[] name, bool dontBroadcast) {
    bool bConnectingHuman = event.GetInt("bot") == 0;
    int client = event.GetInt("index") + 1; // the event provides a player index (entindex - 1)
    
    // client 0, world -- probably not needed any more but just in case
    if (!client) {
        return;
    }
    
    if (bConnectingHuman) {
        if (g_RestartTimer != null) {
            delete g_RestartTimer;
            LogMessage("Player joined server.  Timer killed.");
        }
    } else if (RestartTimerEnabled()) {
        // Make sure this is an actual playing bot.
        if (!IsPlayingBot(client)) {
            return;
        }
        
        bool bAnyHumanConnected = false;
        
        for (int i = MaxClients; i > 0; --i) {
            bAnyHumanConnected |= (IsClientConnected(i) && !IsFakeClient(i));
        }
        
        if (!bAnyHumanConnected && g_RestartTimer == null) {
            g_RestartTimer = CreateTimer(SECONDS_TO_RESTART, OnServerEmptyTooLong);
            LogMessage("Server is empty and a bot has connected.  Starting timer for %f seconds.", SECONDS_TO_RESTART);
        }
    }
}

bool RestartTimerEnabled() {
    // Add time-based checks here.
    return true;
}

bool IsPlayingBot(int client) {
    return !IsClientSourceTV(client) && !IsClientReplay(client);
}

// Server has not killed the timer that was set 20 minutes ago.  Time to restart.
public Action OnServerEmptyTooLong(Handle timer, any data) {
    LogMessage("Server has been empty for %f seconds.  Restarting.", SECONDS_TO_RESTART);
    ServerCommand("quit"); // I assume you have your server configured to restart on shutdown.
}
__________________
I do TF2, TF2 servers, and TF2 plugins.
I don't do DMs over Discord -- PM me on the forums regarding inquiries.
AlliedModders Releases / Github / TF2 Server / Donate (BTC / BCH / coffee)

Last edited by nosoop; 11-27-2020 at 23:12. Reason: fix index value
nosoop is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 03:25.


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