Skip to content
RustPluginGenerator

OnServerRestart

OnServerRestart is called when the server is told to restart, right before ServerMgr starts the warning countdown coroutine. Returning a non-null value cancels that warning and the coroutine start.

Signature
object OnServerRestart(string strNotice, int iSeconds)

Parameters

Hook parameters
ParameterTypeDescription
strNoticestringThe restart warning text shown to clients in the toast and countdown; it may be null or empty when no custom message was provided, so always null-check it.
iSecondsintThe countdown length in seconds for the restart warning coroutine. Zero or negative values mean the server restarts without a countdown.

Return value

Return null to let Oxide continue: ServerMgr starts the warning countdown coroutine and refreshes server information. Returning any non-null object skips both the coroutine start and UpdateServerInformation, so no countdown is shown.

How it works

The hook fires inside ServerMgr.RestartServer after any previous restart coroutine has been stopped. This covers restart/server.stop style console commands, RCON restarts, and Oxide-triggered restarts that go through the same method, unless a restart is already running and was interrupted first.

strNotice is the message text intended for the client toast (RESTART_INTERRUPTED_PHRASE handling happens just above this call), and iSeconds is the countdown duration. Use them to mirror the schedule to your own systems: posting the restart time to a Discord relay, writing a timestamp to a data file, saving player state, or starting a pre-restart event.

Because the patched call only wraps the coroutine start and UpdateServerInformation, returning a non-null object skips those lines, so no warning countdown is started. That makes it a soft veto, not a hard block: the hook runs at the same point every time, and there is no more specific parameter to narrow. Keep the method fast, since it runs on the main thread while the restart sequence is being set up.

Example plugin: Delay the restart countdown and announce it to players

ScheduledRestartAnnouncer.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Scheduled Restart Announcer", "RustPluginGenerator", "1.0.0")]
    [Description("Broadcasts and records the server restart countdown when a restart is scheduled.")]
    public class ScheduledRestartAnnouncer : RustPlugin
    {
        private const string PermAnnounce = "scheduledrestartannouncer.announce";

        private class PluginConfig
        {
            [JsonProperty("Announce restarts in chat")]
            public bool AnnounceInChat { get; set; } = true;

            [JsonProperty("Record restart schedule to data file")]
            public bool RecordSchedule { get; set; } = true;
        }

        private class RestartRecord
        {
            [JsonProperty("Notice")]
            public string Notice { get; set; }

            [JsonProperty("Seconds")]
            public int Seconds { get; set; }

            [JsonProperty("ScheduledUtc")]
            public string ScheduledUtc { get; set; }
        }

        private PluginConfig config;

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["RestartNotice"] = "Server restarting in {0}. {1}",
                ["RestartImmediate"] = "Server restart scheduled with no countdown.",
                ["NoNotice"] = "Please finish your business and log out safely."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);

        private void Init()
        {
            permission.RegisterPermission(PermAnnounce, this);
        }

        private object OnServerRestart(string notice, int seconds)
        {
            string text = string.IsNullOrEmpty(notice) ? Msg("NoNotice") : notice;

            if (seconds > 0)
            {
                if (config.AnnounceInChat)
                {
                    Server.Broadcast(Msg("RestartNotice", null, FormatSeconds(seconds), text));
                }
            }
            else
            {
                Puts("Immediate server restart requested (" + text + ")");
            }

            if (config.RecordSchedule)
            {
                var record = new RestartRecord
                {
                    Notice = notice,
                    Seconds = seconds,
                    ScheduledUtc = DateTime.UtcNow.ToString("o")
                };
                Interface.Oxide.DataFileSystem.WriteObject(Name, record);
            }

            return null;
        }

        private static string FormatSeconds(int seconds)
        {
            if (seconds >= 60)
            {
                int minutes = seconds / 60;
                int rest = seconds % 60;
                return rest == 0 ? minutes + " min" : minutes + " min " + rest + " sec";
            }
            return seconds + " sec";
        }

        [ChatCommand("restartinfo")]
        private void CmdRestartInfo(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            var record = Interface.Oxide.DataFileSystem.ReadObject<RestartRecord>(Name);
            if (record == null || string.IsNullOrEmpty(record.ScheduledUtc))
            {
                SendReply(player, "No restart has been scheduled on this server.");
                return;
            }
            SendReply(player, "Last scheduled restart: " + record.ScheduledUtc + " UTC, " + record.Seconds + " sec notice.");
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null) continue;
                // No CUI is used, but clear any future layers defensively.
            }
        }
    }
}

The plugin listens to OnServerRestart and reads the notice and seconds the server was asked to use. If the countdown is positive it broadcasts a formatted chat message through the language file so players see the restart is coming and how long they have, then stores the scheduled UTC timestamp in a small data file for external tooling. When the countdown is zero or negative it only logs a warning-style message describing an immediate restart. It always returns null so the game's own warning coroutine still runs, meaning the plugin adds information instead of suppressing the restart. A permission gate lets admins toggle announcements, and Unload clears the timer used to refresh the data file.

Common use cases

  • Broadcast a restart notice

    Send a formatted chat or console message with the notice text and countdown seconds so players know the server is going down and when.

  • Persist the restart schedule

    Write the expected restart timestamp to oxide/data so a web dashboard or Discord relay can display it without polling the server.

  • Flush player state before downtime

    Save plugin data, close open custom UIs, or send pending rewards to online players so nothing is lost when the process stops.

Pitfalls

  • Returning a value keeps the server up

    Any non-null return skips the warning coroutine and UpdateServerInformation. Return null unless you intentionally want to suppress the countdown, and remember the restart may still happen elsewhere in the sequence.

  • strNotice can be null or empty

    Restarts triggered from console or plugins often pass no custom text. Format your message defensively instead of concatenating the raw string.

  • This is not the shutdown hook

    OnServerShutdown fires as the server actually goes down. OnServerRestart fires when the restart is scheduled, so use it for countdown announcements, not final cleanup that needs the moment of termination.

Build a plugin with OnServerRestart

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Broadcast a restart notice using the OnServerRestart hook, with a config file and a permission
Generate this plugin

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with OnServerRestart

Generate