Иконка ресурса

FREE AutoRestart : 2.1.1 2.1.1

Нет прав для скачивания
C#:
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("AutoRestart", "crash", "2.1.1")]
    [Description("All features are managed through an intuitive UI")]
    public class AutoRestart : RustPlugin
    {
        #region Fields

        private const string CurrentVersion = "2.1.1";
        private const int DISCORD_SUCCESS_CODE = 204;
        private const float DISCORD_ONLINE_DELAY = 300f;
        private const float RESTART_DELAY = 65f;
        private const string PERMISSION_USE = "autorestart.use";
        private const string CHECKBOX_ON_SOUND = "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab";
        private const string CHECKBOX_OFF_SOUND = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";

        private ConfigData config;
        private List<int> notifiedWarningTimes = new List<int>();
        private Dictionary<string, string> _inputFieldValues = new Dictionary<string, string>();
        private static bool hasSentDiscordOnlineNotification = false;
        private List<TimeSpan> restartTimes = new List<TimeSpan>();
        private Timer nextRestartTimer;
        private bool isCustomRestart = false;
        private bool isCancelled = false;
        private bool isCustomUICreated = false;
        private int customRestartTime = 0;
        private List<Timer> activeTimers = new List<Timer>();
        private string lastChatMessage = string.Empty;
        private string lastUIMessage = string.Empty;
        #endregion

        #region Configuration

        private class ConfigData
        {
            public string Version { get; set; } = CurrentVersion;
            public RestartConfig Restart { get; set; } = new RestartConfig();
            public PlayerRestrictionConfig PlayerRestrictions { get; set; } = new PlayerRestrictionConfig();
            public AlertConfig Alerts { get; set; } = new AlertConfig();
            public UpdateCheckConfig UpdateCheck { get; set; } = new UpdateCheckConfig();
            public UIConfig UI { get; set; } = new UIConfig();
            public DiscordConfig Discord { get; set; } = new DiscordConfig();
        }

        private class RestartConfig
        {
            public List<string> RestartTimes { get; set; } = new List<string>();
            public string AlertSound { get; set; } = "assets/prefabs/locks/keypad/effects/lock.code.lock.prefab";
            public bool UseSound { get; set; } = true;
            public bool UseChatAlerts { get; set; } = true;
        }

        private class PlayerRestrictionConfig
        {
            public int MaxPlayersBeforeCancel { get; set; } = 10;
            public bool RestrictPlayerCount { get; set; } = false;
        }

        public class AlertConfig
        {
            public List<int> WarningTimes { get; set; } = new List<int>();
        }

        private class UpdateCheckConfig
        {
            public bool CheckForUpdates { get; set; } = false;
            public int CheckInterval { get; set; } = 600;
        }

        private class UIConfig
        {
            public bool UseCustomUI { get; set; } = false;
            public bool UseRustUI { get; set; } = true;
            public CustomUISettings CustomUI { get; set; } = new CustomUISettings();
        }

        private class CustomUISettings
        {
            public string AnchorMin { get; set; } = "0 0.5";
            public string AnchorMax { get; set; } = "0 0.5";
            public string OffsetMin { get; set; } = "10 -45.9695";
            public string OffsetMax { get; set; } = "177.325 46.7435";
            public string CheckIcon { get; set; } = "✓";
            public string CrossIcon { get; set; } = "✗";
            public string CheckIconColor { get; set; } = "0.5568627 0.7764706 0.1843137 1";
            public string CrossIconColor { get; set; } = "0.7764706 0.5137255 0.4196078 1";

            [JsonIgnore]
            public string BackgroundColor
            {
                get => _backgroundColor;
                set
                {
                    _backgroundColor = value;
                    BackgroundColorHex = value.ToHex();
                }
            }

            private string _backgroundColor = "0.3137255 0.5843138 0.772549 0.85";

            public string BackgroundColorHex { get; private set; } = "#5094C5";

            public int TitleFontSize { get; set; } = 12;
            public int MessageFontSize { get; set; } = 10;
        }

        private class DiscordConfig
        {
            public string WebhookUrl { get; set; } = "https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks";

            public string ServerName { get; set; } = "Rust Server";
            public bool DiscordNotifications { get; set; } = false;
        }

        #endregion

        #region Oxide Hooks

        private void Init()
        {
            permission.RegisterPermission(PERMISSION_USE, this);
            LoadConfigValues();
            UpdateLanguage();
            ScheduleNextRestart();

            if (config.UpdateCheck.CheckForUpdates)
            {
                CheckForUpdates();
            }
        }

        private void OnServerInitialized()
        {
            try 
            {
                NotifyDiscordOnline();
        
                // Esperar un momento para asegurarnos que todo esté inicializado
                timer.Once(5f, () =>
                {
                    LogInfo("Initializing restart schedule...");
                    LogInfo($"Configured restart times: {string.Join(", ", restartTimes.Select(t => t.ToString(@"hh\:mm")))}");
            
                    // Limpiar cualquier estado anterior
                    ClearAllTimers();
                    isCustomRestart = false;
                    isCancelled = false;
                    customRestartTime = 0;
                    notifiedWarningTimes.Clear();

                    // Programar el primer reinicio
                    ScheduleNextRestart();
            
                    // Programar una verificación periódica del estado
                    timer.Every(3600f, () =>
                    {
                        if (nextRestartTimer != null)
                        {
                            var nextRestart = DateTime.UtcNow.AddSeconds(nextRestartTimer.Repetitions);
                            LogInfo($"Periodic check - Next restart at: {nextRestart} UTC");
                        }
                        else
                        {
                            LogWarning("Periodic check - No restart scheduled! Attempting to reschedule...");
                            ScheduleNextRestart();
                        }
                    });
                });
            }
            catch (Exception ex)
            {
                LogError($"Error in OnServerInitialized: {ex}", ex);
            }
        }

        private void OnPlayerInit(BasePlayer player)
        {
            if (!string.IsNullOrEmpty(lastUIMessage))
            {
                ShowMessage(lastUIMessage, false);
            }
        }

        void Unload()
        {
            ClearAllTimers();
            DestroyAllUI();
        }

        #endregion

        #region Configuration Methods

        protected override void LoadDefaultConfig()
        {
            config = new ConfigData
            {
                Alerts = new AlertConfig
                {
                    WarningTimes = new List<int>()
                }
            };

            Puts("[AutoRestart] Default config loaded without default WarningTimes.");
            
            SaveConfig();
        }

        private void SaveConfig()
        {
            Puts("[AutoRestart] Saving configuration to AutoRestart.json");
            Config.WriteObject(config, true);
            Puts("[AutoRestart] Configuration written to AutoRestart.json, please reload the plugin.");
        }

        private void LoadConfigValues()
        {
            if (!Config.Exists())
            {
                Puts("[AutoRestart] Config does not exist, creating empty config.");
                LoadDefaultConfig();
                return;
            }

            config = Config.ReadObject<ConfigData>();
            
            if (config.Alerts.WarningTimes == null)
            {
                config.Alerts.WarningTimes = new List<int>();
            }

            if (config.Version != CurrentVersion)
            {
                Puts("[AutoRestart] Config version mismatch, updating config.");
                UpdateConfig();
            }
            
            config.UI.CustomUI.BackgroundColor = config.UI.CustomUI.BackgroundColor;

            LoadRestartTimes();
        }


        private void UpdateConfig()
        {
            PrintWarning("Updating configuration to the latest version.");
            
            config.Version = CurrentVersion;

            SaveConfig();
            PrintWarning("Configuration updated successfully.");
        }

        private void LoadRestartTimes()
        {
            try
            {
                LogInfo("Loading restart times...");
                restartTimes.Clear();
                HashSet<TimeSpan> uniqueRestartTimes = new HashSet<TimeSpan>();
        
                foreach (var timeString in config.Restart.RestartTimes)
                {
                    if (TimeSpan.TryParse(timeString, out TimeSpan restartTime))
                    {
                        if (uniqueRestartTimes.Add(restartTime))
                        {
                            restartTimes.Add(restartTime);
                            LogInfo($"Restart time added: {timeString}");
                        }
                        else
                        {
                            LogWarning($"Duplicate restart time ignored: {timeString}");
                        }
                    }
                    else
                    {
                        LogError($"Invalid time format: {timeString}");
                    }
                }

                LogInfo($"Total restart times loaded: {restartTimes.Count}");
            }
            catch (Exception ex)
            {
                LogError("Error loading restart times", ex);
            }
        }

        #endregion

        #region Language Methods

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(GetDefaultMessages(), this);
        }

        private void UpdateLanguage()
        {
            var langFile = $"{Name}.json";
            var langPath = Path.Combine(Interface.Oxide.LangDirectory, "en", langFile);

            Dictionary<string, string> messages;
            if (File.Exists(langPath))
            {
                messages = Config.ReadObject<Dictionary<string, string>>(langPath);
            }
            else
            {
                messages = new Dictionary<string, string>();
            }

            var currentVersion = messages.ContainsKey("Version") ? messages["Version"] : "0.0.0";

            if (currentVersion != CurrentVersion)
            {
                UpdateLanguageFile(messages, langPath);
            }

            lang.RegisterMessages(messages, this);
        }

        private void UpdateLanguageFile(Dictionary<string, string> messages, string langPath)
        {
            PrintWarning($"Updating language file from version {messages["Version"]} to {CurrentVersion}");

            var defaultMessages = GetDefaultMessages();
            bool changed = false;

            foreach (var entry in defaultMessages)
            {
                if (!messages.ContainsKey(entry.Key) || messages[entry.Key] != entry.Value)
                {
                    messages[entry.Key] = entry.Value;
                    changed = true;
                }
            }

            if (changed)
            {
                messages["Version"] = CurrentVersion;
                Config.WriteObject(messages, false, langPath);
                PrintWarning($"Language file updated successfully.New version: {CurrentVersion}");
            }
        }

        private Dictionary<string, string> GetDefaultMessages()
        {
            var messages = new Dictionary<string, string>
            {
                ["Version"] = CurrentVersion,
                ["ChatRestartAlert"] = "Server restart scheduled in {0}.",
                ["ChatRestartCanceled"] = "The server restart has been canceled.",
                ["ChatRestartNow"] = "RESTARTING...",
                ["ChatRestartCanceledTooManyPlayers"] = "Restart canceled due to too many players.",
                ["NoRestartScheduled"] = "No restart is currently scheduled.",
                ["RustUITitle"] = "SCHEDULED SERVER RESTART",
                ["RustUIMessage"] = "The server will restart in {0}.",
                ["CustomUITitle"] = "SCHEDULED SERVER RESTART",
                ["CustomUIMessage"] = "The server will restart in {0}.",
                ["NoPermission"] = "You do not have permission to use this command.",
                ["Usage"] = "Usage: /restart <seconds>",
                ["InvalidNumber"] = "Invalid number of seconds provided.",
                ["UpdateDetected"] = "A uMod update has been detected.The server will restart to apply the update.",
                ["DiscordRestartAlert"] = "🔄 **SERVER RESTART**\nServer will restart in {0}.",
                ["DiscordRestarting"] = "⚠️ **RESTARTING**\nServer is restarting now.Please wait 5 minutes for the server to be back online.",
                ["DiscordOnline"] = "✅ **SERVER ONLINE**\nServer is now online and ready to play!",
                ["TimeMinute"] = "minute",
                ["TimeMinutes"] = "minutes",
                ["TimeHour"] = "hour",
                ["TimeHours"] = "hours",
                ["TimeSecond"] = "second",
                ["TimeSeconds"] = "seconds"
            };

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Version"] = CurrentVersion,
                ["ChatRestartAlert"] = "Перезапуск сервера запланирован через {0}.",
                ["ChatRestartCanceled"] = "Перезапуск сервера был отменен.",
                ["ChatRestartNow"] = "ПЕРЕЗАПУСК...",
                ["ChatRestartCanceledTooManyPlayers"] = "Перезапуск отменен из-за большого количества игроков.",
                ["NoRestartScheduled"] = "В настоящее время перезапуск не запланирован.",
                ["RustUITitle"] = "ЗАПЛАНИРОВАННЫЙ ПЕРЕЗАПУСК СЕРВЕРА",
                ["RustUIMessage"] = "Сервер перезапустится через {0}.",
                ["CustomUITitle"] = "ЗАПЛАНИРОВАННЫЙ ПЕРЕЗАПУСК СЕРВЕРА",
                ["CustomUIMessage"] = "Сервер перезапустится через {0}.",
                ["NoPermission"] = "У вас нет прав для использования этой команды.",
                ["Usage"] = "Использование: /restart <секунды>",
                ["InvalidNumber"] = "Указано неверное количество секунд.",
                ["UpdateDetected"] = "Обнаружено обновление uMod.Сервер будет перезапущен для применения обновления.",
                ["TimeMinute"] = "минута",
                ["TimeMinutes"] = "минут",
                ["TimeHour"] = "час",
                ["TimeHours"] = "часов",
                ["TimeSecond"] = "секунда",
                ["TimeSeconds"] = "секунд"
            }, this, "ru");

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Version"] = CurrentVersion,
                ["ChatRestartAlert"] = "Перезапуск сервера заплановано через {0}.",
                ["ChatRestartCanceled"] = "Перезапуск сервера було скасовано.",
                ["ChatRestartNow"] = "ПЕРЕЗАПУСК...",
                ["ChatRestartCanceledTooManyPlayers"] = "Перезапуск скасовано через велику кількість гравців.",
                ["NoRestartScheduled"] = "На даний момент перезапуск не заплановано.",
                ["RustUITitle"] = "ЗАПЛАНОВАНИЙ ПЕРЕЗАПУСК СЕРВЕРА",
                ["RustUIMessage"] = "Сервер перезапуститься через {0}.",
                ["CustomUITitle"] = "ЗАПЛАНОВАНИЙ ПЕРЕЗАПУСК СЕРВЕРА",
                ["CustomUIMessage"] = "Сервер перезапуститься через {0}.",
                ["NoPermission"] = "У вас немає прав для використання цієї команди.",
                ["Usage"] = "Використання: /restart <секунди>",
                ["InvalidNumber"] = "Вказано невірну кількість секунд.",
                ["UpdateDetected"] = "Виявлено оновлення uMod.Сервер буде перезапущено для застосування оновлення.",
                ["TimeMinute"] = "хвилина",
                ["TimeMinutes"] = "хвилин",
                ["TimeHour"] = "година",
                ["TimeHours"] = "годин",
                ["TimeSecond"] = "секунда",
                ["TimeSeconds"] = "секунд"
            }, this, "uk");

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Version"] = CurrentVersion,
                ["ChatRestartAlert"] = "Riavvio del server programmato tra {0}.",
                ["ChatRestartCanceled"] = "Il riavvio del server è stato annullato.",
                ["ChatRestartNow"] = "RIAVVIO IN CORSO...",
                ["ChatRestartCanceledTooManyPlayers"] = "Riavvio annullato a causa di troppi giocatori.",
                ["NoRestartScheduled"] = "Nessun riavvio programmato al momento.",
                ["RustUITitle"] = "RIAVVIO SERVER PROGRAMMATO",
                ["RustUIMessage"] = "Il server verrà riavviato tra {0}.",
                ["CustomUITitle"] = "RIAVVIO SERVER PROGRAMMATO",
                ["CustomUIMessage"] = "Il server verrà riavviato tra {0}.",
                ["NoPermission"] = "Non hai il permesso di utilizzare questo comando.",
                ["Usage"] = "Utilizzo: /restart <secondi>",
                ["InvalidNumber"] = "Numero di secondi non valido.",
                ["UpdateDetected"] = "È stato rilevato un aggiornamento di uMod.Il server verrà riavviato per applicare l'aggiornamento.",
                ["TimeMinute"] = "minuto",
                ["TimeMinutes"] = "minuti",
                ["TimeHour"] = "ora",
                ["TimeHours"] = "ore",
                ["TimeSecond"] = "secondo",
                ["TimeSeconds"] = "secondi"
            }, this, "it");

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Version"] = CurrentVersion,
                ["ChatRestartAlert"] = "Reinicio del servidor programado en {0}.",
                ["ChatRestartCanceled"] = "El reinicio del servidor ha sido cancelado.",
                ["ChatRestartNow"] = "REINICIANDO...",
                ["ChatRestartCanceledTooManyPlayers"] = "Reinicio cancelado debido a demasiados jugadores.",
                ["NoRestartScheduled"] = "No hay reinicio programado actualmente.",
                ["RustUITitle"] = "REINICIO DE SERVIDOR PROGRAMADO",
                ["RustUIMessage"] = "El servidor se reiniciará en {0}.",
                ["CustomUITitle"] = "REINICIO DE SERVIDOR PROGRAMADO",
                ["CustomUIMessage"] = "El servidor se reiniciará en {0}.",
                ["NoPermission"] = "No tienes permiso para usar este comando.",
                ["Usage"] = "Uso: /restart <segundos>",
                ["InvalidNumber"] = "Número de segundos proporcionado no válido.",
                ["UpdateDetected"] = "Se ha detectado una actualización de uMod.El servidor se reiniciará para aplicar la actualización.",
                ["TimeMinute"] = "minuto",
                ["TimeMinutes"] = "minutos",
                ["TimeHour"] = "hora",
                ["TimeHours"] = "horas",
                ["TimeSecond"] = "segundo",
                ["TimeSeconds"] = "segundos"
            }, this, "es-ES");

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Version"] = CurrentVersion,
                ["ChatRestartAlert"] = "Reinício do servidor programado em {0}.",
                ["ChatRestartCanceled"] = "O reinício do servidor foi cancelado.",
                ["ChatRestartNow"] = "REINICIANDO...",
                ["ChatRestartCanceledTooManyPlayers"] = "Reinício cancelado devido ao excesso de jogadores.",
                ["NoRestartScheduled"] = "Nenhum reinício está programado no momento.",
                ["RustUITitle"] = "REINÍCIO DO SERVIDOR PROGRAMADO",
                ["RustUIMessage"] = "O servidor será reiniciado em {0}.",
                ["CustomUITitle"] = "REINÍCIO DO SERVIDOR PROGRAMADO",
                ["CustomUIMessage"] = "O servidor será reiniciado em {0}.",
                ["NoPermission"] = "Você não tem permissão para usar este comando.",
                ["Usage"] = "Uso: /restart <segundos>",
                ["InvalidNumber"] = "Número de segundos fornecido inválido.",
                ["UpdateDetected"] = "Uma atualização do uMod foi detectada.O servidor será reiniciado para aplicar a atualização.",
                ["TimeMinute"] = "minuto",
                ["TimeMinutes"] = "minutos",
                ["TimeHour"] = "hora",
                ["TimeHours"] = "horas",
                ["TimeSecond"] = "segundo",
                ["TimeSeconds"] = "segundos"
            }, this, "pt-BR");

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Version"] = CurrentVersion,
                ["ChatRestartAlert"] = "Redémarrage du serveur prévu dans {0}.",
                ["ChatRestartCanceled"] = "Le redémarrage du serveur a été annulé.",
                ["ChatRestartNow"] = "REDÉMARRAGE...",
                ["ChatRestartCanceledTooManyPlayers"] = "Redémarrage annulé en raison de trop de joueurs.",
                ["NoRestartScheduled"] = "Aucun redémarrage n'est actuellement prévu.",
                ["RustUITitle"] = "REDÉMARRAGE DU SERVEUR PROGRAMMÉ",
                ["RustUIMessage"] = "Le serveur redémarrera dans {0}.",
                ["CustomUITitle"] = "REDÉMARRAGE DU SERVEUR PROGRAMMÉ",
                ["CustomUIMessage"] = "Le serveur redémarrera dans {0}.",
                ["NoPermission"] = "Vous n'avez pas la permission d'utiliser cette commande.",
                ["Usage"] = "Utilisation: /restart <secondes>",
                ["InvalidNumber"] = "Nombre de secondes fourni non valide.",
                ["UpdateDetected"] = "Une mise à jour uMod a été détectée.Le serveur va redémarrer pour appliquer la mise à jour.",
                ["TimeMinute"] = "minute",
                ["TimeMinutes"] = "minutes",
                ["TimeHour"] = "heure",
                ["TimeHours"] = "heures",
                ["TimeSecond"] = "seconde",
                ["TimeSeconds"] = "secondes"
            }, this, "fr");

            return messages;
        }

        #endregion

        #region Command Handlers

        [ChatCommand("crestart")]
        private void CmdCRestart(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PERMISSION_USE))
            {
                player.ChatMessage(GetLang("NoPermission", player.UserIDString));
                return;
            }

            ShowCRestartUI(player);
        }

        [ChatCommand("restart")]
        private void RestartCommand(BasePlayer player, string command, string[] args)
        {
            if (!HasPermission(player))
            {
                player.ChatMessage(GetLang("NoPermission", player.UserIDString));
                return;
            }

            if (args.Length < 1)
            {
                player.ChatMessage(GetLang("Usage", player.UserIDString));
                return;
            }

            // Simpler number parsing
            if (!int.TryParse(args[0], out int seconds) || seconds <= 0)
            {
                player.ChatMessage(GetLang("InvalidNumber", player.UserIDString));
                return;
            }

            StartCustomRestart(seconds);
        }

        [ChatCommand("restartstop")]
        private void ChatRestartStopCommand(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PERMISSION_USE))
            {
                SendReply(player, GetLang("NoPermission", player.UserIDString));
                return;
            }

            if (isCustomRestart || nextRestartTimer != null)
            {
                CancelRestart();
            }
            else
            {
                SendReply(player, GetLang("NoRestartActive", player.UserIDString));
            }
        }

        [ConsoleCommand("restart")]
        private void ConsoleRestartCommand(ConsoleSystem.Arg arg)
        {
            if (arg.IsServerside || arg.IsAdmin)
            {
                if (arg.Args == null || arg.Args.Length < 1)
                {
                    Puts("Usage: restart <seconds>");
                    return;
                }

                if (int.TryParse(arg.Args[0], out int seconds))
                {
                    StartCustomRestart(seconds);
                    Puts($"Initiated a custom restart in {seconds} seconds.");
                }
                else
                {
                    Puts("Invalid number of seconds provided.");
                }
            }
            else
            {
                Puts("You don't have permission to use this command.");
            }
        }

        [ConsoleCommand("restartstop")]
        private void ConsoleRestartStopCommand(ConsoleSystem.Arg arg)
        {
            if (arg.IsServerside || arg.IsAdmin)
            {
                if (isCustomRestart || nextRestartTimer != null)
                {
                    CancelRestart();
                }
                else
                {
                    Puts("No restart is currently scheduled.");
                }
            }
            else
            {
                Puts("You don't have permission to use this command.");
            }
        }
        
        [ConsoleCommand("restart.list")]
        private void CmdListNextRestarts(ConsoleSystem.Arg arg)
        {
            if (!arg.IsAdmin) return;

            var sb = new StringBuilder();
            sb.AppendLine("Upcoming Restarts (UTC):");
    
            DateTime now = DateTime.UtcNow;
            var upcomingRestarts = new List<DateTime>();
    
            // Obtener reinicios para hoy
            foreach (var time in restartTimes)
            {
                var todayTime = now.Date.Add(time);
                if (todayTime > now)
                {
                    upcomingRestarts.Add(todayTime);
                }
            }
    
            // Obtener reinicios para mañana
            foreach (var time in restartTimes)
            {
                upcomingRestarts.Add(now.Date.AddDays(1).Add(time));
            }
    
            // Mostrar los próximos 5 reinicios
            foreach (var restart in upcomingRestarts.OrderBy(x => x).Take(5))
            {
                var timeUntil = restart - now;
                sb.AppendLine($"- {restart:yyyy-MM-dd HH:mm:ss} (in {timeUntil.TotalHours:F1} hours)");
            }

            Puts(sb.ToString());
        }

        [ConsoleCommand("crestart.toggle")]
        private void CmdToggleSetting(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !permission.UserHasPermission(player.UserIDString, PERMISSION_USE)) return;

            var setting = arg.GetString(0);
            bool newValue = !GetConfigValue(setting);
            SetConfigValue(setting, newValue);

            string soundEffect = newValue ? CHECKBOX_ON_SOUND : CHECKBOX_OFF_SOUND;
            Effect.server.Run(soundEffect, player.transform.position);

            Puts($"[AutoRestart] Toggled setting: {setting} to {newValue}");
            SaveConfig();
    
            ShowCRestartUI(player);
        }
        
        [ConsoleCommand("crestart.input")]
        private void CmdInputSetting(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !permission.UserHasPermission(player.UserIDString, PERMISSION_USE)) return;

            if (arg.Args == null || arg.Args.Length < 2)
            {
                PrintError("Insufficient arguments provided for crestart.input command.");
                return;
            }

            string setting = arg.Args[0];
            string value = string.Join(" ", arg.Args.Skip(1).ToArray());

            Puts($"[AutoRestart] Received input for setting: {setting}, with value: {value}");
    
            string key = $"{player.UserIDString}_{setting}";
            _inputFieldValues[key] = value;

            if (string.IsNullOrEmpty(value))
            {
                Puts($"[AutoRestart] Error: No value provided for setting {setting}");
                return;
            }

            switch (setting)
            {
                case "WarningTimes":
                    try
                    {
                        var newWarningTimes = value.Split(',').Select(s => int.Parse(s.Trim())).Where(i => i > 0).Distinct().OrderByDescending(x => x).ToList();

                        config.Alerts.WarningTimes = newWarningTimes;
                        Puts($"[AutoRestart] Updated WarningTimes: {string.Join(", ", config.Alerts.WarningTimes)}");
                    }
                    catch (FormatException)
                    {
                        PrintError($"[AutoRestart] Invalid format for WarningTimes: {value}");
                    }
                    break;

                case "RestartTimes":
                    try
                    {
                        var newRestartTimes = value.Split(',').Select(s => s.Trim()).ToList();
                        config.Restart.RestartTimes = newRestartTimes;
                        LoadRestartTimes();
                        Puts($"[AutoRestart] Updated RestartTimes: {string.Join(", ", config.Restart.RestartTimes)}");
                    }
                    catch (Exception ex)
                    {
                        PrintError($"[AutoRestart] Error updating RestartTimes: {ex.Message}");
                    }
                    break;
                case "AlertSound":
                    config.Restart.AlertSound = value;
                    Puts($"[AutoRestart] Updated AlertSound: {value}");
                    break;
                case "MaxPlayersBeforeCancel":
                    if (int.TryParse(value, out int maxPlayers))
                    {
                        config.PlayerRestrictions.MaxPlayersBeforeCancel = maxPlayers;
                        Puts($"[AutoRestart] Updated MaxPlayersBeforeCancel: {maxPlayers}");
                    }
                    else
                    {
                        PrintError($"[AutoRestart] Invalid MaxPlayersBeforeCancel value: {value}");
                    }
                    break;
                case "CheckInterval":
                    if (int.TryParse(value, out int interval))
                    {
                        config.UpdateCheck.CheckInterval = interval;
                        Puts($"[AutoRestart] Updated CheckInterval: {interval}");
                    }
                    else
                    {
                        PrintError($"[AutoRestart] Invalid CheckInterval value: {value}");
                    }
                    break;
                case "WebhookUrl":
                    config.Discord.WebhookUrl = value;
                    Puts($"[AutoRestart] Updated WebhookUrl: {value}");
                    break;
                case "ServerName":
                    config.Discord.ServerName = value;
                    Puts($"[AutoRestart] Updated ServerName: {value}");
                    break;
                default:
                    Puts($"[AutoRestart] Setting '{setting}' is not recognized.");
                    return;
            }

            SaveConfig();
            LoadConfigValues();
            UpdateCRestartUI(player);
        }


        [ConsoleCommand("crestart.submit")]
        private void CmdSubmitSetting(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !permission.UserHasPermission(player.UserIDString, PERMISSION_USE)) return;

            var setting = arg.GetString(0);
            var value = arg.GetString(1, "");

            if (string.IsNullOrEmpty(value))
            {
                Puts($"Error: No value provided for setting {setting}");
                return;
            }

            UpdateConfigValue(setting, value);
            SaveConfig();
            Puts($"Config updated: {setting} = {value}");
            ShowCRestartUI(player);
        }
        
        private void UpdateConfigValue(string setting, string value)
        {
            switch (setting)
            {
                case "AlertSound":
                    config.Restart.AlertSound = value;
                    break;
                case "MaxPlayersBeforeCancel":
                    if (int.TryParse(value, out int maxPlayers))
                        config.PlayerRestrictions.MaxPlayersBeforeCancel = maxPlayers;
                    break;
                case "CheckInterval":
                    if (int.TryParse(value, out int interval))
                        config.UpdateCheck.CheckInterval = interval;
                    break;
                case "WebhookUrl":
                    config.Discord.WebhookUrl = value;
                    break;
                case "ServerName":
                    config.Discord.ServerName = value;
                    break;
                case "WarningTimes":
                    try
                    {
                        config.Alerts.WarningTimes = value.Split(',').Select(s => int.Parse(s.Trim())).Where(i => i > 0).ToList();
                    }
                    catch (FormatException)
                    {
                        PrintError($"Invalid WarningTimes format: {value}");
                    }
                    break;
                case "RestartTimes":
                    try
                    {
                        config.Restart.RestartTimes = value.Split(',').Select(s => s.Trim()).ToList();
                        LoadRestartTimes();
                    }
                    catch (Exception ex)
                    {
                        PrintError($"Invalid RestartTimes format: {value}.Error: {ex.Message}");
                    }
                    break;
            }
        }

        #endregion

        #region Restart Handling Methods

        private void StartCustomRestart(int seconds)
        {
            if (isCustomRestart) return;

            isCustomRestart = true;
            customRestartTime = seconds;
            isCancelled = false;

            ClearAllTimers();
            DestroyAllUI();

            // Crear el timer principal para el reinicio
            Timer countdownTimer = timer.Once(seconds, CheckPlayerCountAndRestart);
            activeTimers.Add(countdownTimer);

            // Mostrar mensaje inicial solo si es mayor a 60 segundos
            if (seconds > 60)
            {
                ShowMessage(seconds.ToString(), false);
                
                if (config.Restart.UseSound)
                {
                    PlaySoundToAllPlayers(config.Restart.AlertSound);
                }

                timer.Once(8f, () =>
                {
                    if (!isCancelled)
                    {
                        DestroyAllUI();
                        isCustomUICreated = false;
                    }
                });

                // Configurar los intervalos de aviso
                List<int> warningIntervals = new List<int>();
                
                if (config.Alerts.WarningTimes != null && config.Alerts.WarningTimes.Count > 0)
                {
                    warningIntervals = config.Alerts.WarningTimes.Select(minutes => minutes * 60).Where(secs => secs < seconds).OrderByDescending(secs => secs).ToList();
                }
                else
                {
                    int[] defaultIntervals = { 1800, 900, 600, 300 };
                    warningIntervals = defaultIntervals.Where(secs => secs < seconds).ToList();
                }

                foreach (int interval in warningIntervals)
                {
                    Timer warningTimer = timer.Once(seconds - interval, () =>
                    {
                        if (!isCancelled)
                        {
                            ShowMessage(interval.ToString(), false);
                            if (config.Restart.UseSound)
                            {
                                PlaySoundToAllPlayers(config.Restart.AlertSound);
                            }

                            timer.Once(8f, () =>
                            {
                                if (!isCancelled)
                                {
                                    DestroyAllUI();
                                    isCustomUICreated = false;
                                }
                            });
                        }
                    });
                    activeTimers.Add(warningTimer);
                }

                // Programar countdown del último minuto
                Timer countdownMinuteTimer = timer.Once(seconds - 60, () =>
                {
                    if (!isCancelled)
                    {
                        CountdownFromMinute();
                    }
                });
                activeTimers.Add(countdownMinuteTimer);
            }
            else
            {
                // Para tiempos menores o iguales a 60 segundos, iniciar el countdown inmediatamente
                timer.Once(0.1f, () => 
                {
                    if (!isCancelled)
                    {
                        CountdownFromMinute();
                    }
                });
            }

            if (config.Discord.DiscordNotifications)
            {
                NotifyDiscord(seconds);
            }

            LogInfo($"Custom restart scheduled for {seconds} seconds from now.Current time: {DateTime.UtcNow}");
        }

        private void CancelRestart()
        {
            if (isCancelled) return;

            isCancelled = true;
            ClearAllTimers();
            notifiedWarningTimes.Clear();

            foreach (var player in BasePlayer.activePlayerList)
            {
                string cancelMessage = GetLang("ChatRestartCanceled", player.UserIDString);

                player.ChatMessage(cancelMessage);

                if (config.UI.UseCustomUI)
                {
                    ShowCustomUI(player, cancelMessage, true);
                }

                if (config.UI.UseRustUI)
                {
                    string title = GetLang("RustUITitle", player.UserIDString);
                    player.SendConsoleCommand("gametip.showgametip",
                        $"<size=20>{title}</size>\n<size=14>{cancelMessage}</size>");
                }
            }

            if (!isCustomRestart && nextRestartTimer != null)
            {
                ReScheduleNextRestartForNextDay();
            }
            else
            {
                ResetRestartState();
            }

            timer.Once(5f, () => 
            {
                DestroyAllUI();
                isCustomUICreated = false;
            });
        }
        
        private void ShowCancelMessageAndDestroyUI(string cancelMessage)
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                string localizedMessage = GetLang("ChatRestartCanceled", player.UserIDString);
        
                if (config.UI.UseCustomUI)
                {
                    ShowCustomUI(player, localizedMessage, true);
                }

                if (config.UI.UseRustUI)
                {
                    player.SendConsoleCommand("gametip.hidegametip");
                    player.SendConsoleCommand("gametip.showgametip",
                        $"<size=20>{GetLang("RustUITitle", player.UserIDString)}</size>\n<size=14>{localizedMessage}</size>");
                }
            }

            timer.Once(5f, () => 
            {
                DestroyAllUI();
                isCustomUICreated = false;
            });
        }

        private void BroadcastCancelMessage(string cancelMessage)
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                string localizedMessage = GetLang("ChatRestartCanceled", player.UserIDString);
                player.ChatMessage(localizedMessage);
            }

            if (config.Discord.DiscordNotifications)
            {
                SendDiscordNotification(GetLang("ChatRestartCanceled", null));
            }
        }

        private void ResetRestartState()
        {
            isCustomRestart = false;
            customRestartTime = 0;
            lastChatMessage = string.Empty;
            lastUIMessage = string.Empty;
            isCancelled = false;
        }

        private void ReScheduleNextRestartForNextDay()
        {
            if (restartTimes.Count == 0)
            {
                LogWarning("No restart times are scheduled.");
                return;
            }

            try 
            {
                DateTime now = DateTime.UtcNow;
                DateTime nextRestart = FindNextRestartTime(now);
                TimeSpan timeUntilRestart = nextRestart - now;

                LogInfo($"Rescheduling restart:");
                LogInfo($"Current time (UTC): {now}");
                LogInfo($"Available restart times: {string.Join(", ", restartTimes.Select(t => t.ToString(@"hh\:mm")))}");
                LogInfo($"Next restart time (UTC): {nextRestart}");
                LogInfo($"Time until restart: {timeUntilRestart.TotalHours:F2} hours");

                // Limpiar timers existentes
                ClearAllTimers();

                // Programar el próximo reinicio
                nextRestartTimer = timer.Once((float)timeUntilRestart.TotalSeconds, CheckPlayerCountAndRestart);
                activeTimers.Add(nextRestartTimer);

                // Programar las alertas
                if (config.Alerts.WarningTimes != null && config.Alerts.WarningTimes.Count > 0)
                {
                    ScheduleAlerts(timeUntilRestart);
                }

                // Resetear estados
                isCustomRestart = false;
                isCancelled = false;
                customRestartTime = 0;
                notifiedWarningTimes.Clear();

                LogInfo($"Next restart successfully scheduled for {nextRestart} UTC");
            }
            catch (Exception ex)
            {
                LogError($"Error scheduling next restart: {ex}", ex);
        
                // Intentar recuperarse del error
                timer.Once(300f, ScheduleNextRestart);
            }
        }
        
        private void ScheduleNextRestart()
        {
            // No programar el siguiente reinicio si hay uno personalizado en curso
            if (isCustomRestart)
            {
                LogInfo("Next scheduled restart skipped: custom restart is active");
                return;
            }

            if (isCancelled)
            {
                LogInfo("Next scheduled restart skipped: restart is cancelled");
                return;
            }

            ClearAllTimers();

            if (restartTimes.Count == 0)
            {
                LogWarning("No restart times scheduled");
                return;
            }

            try
            {
                DateTime now = DateTime.UtcNow;
                DateTime nextRestart = FindNextRestartTime(now);
                TimeSpan timeUntilRestart = nextRestart - now;

                // Ensure we're not scheduling in the past
                if (timeUntilRestart.TotalSeconds <= 0)
                {
                    nextRestart = nextRestart.AddDays(1);
                    timeUntilRestart = nextRestart - now;
                }

                nextRestartTimer = timer.Once((float)timeUntilRestart.TotalSeconds, CheckPlayerCountAndRestart);
                activeTimers.Add(nextRestartTimer);

                // Usar los warning times configurados para el reinicio programado
                if (config.Alerts.WarningTimes != null && config.Alerts.WarningTimes.Count > 0)
                {
                    ScheduleAlerts(timeUntilRestart);
                }

                LogInfo($"Next scheduled restart set for: {nextRestart} UTC");
                LogInfo($"Time until restart: {timeUntilRestart.TotalHours:F2} hours");
            }
            catch (Exception ex)
            {
                LogError($"Error scheduling next restart: {ex}", ex);
            }
        }


        private void LogRestartInfo(DateTime now, DateTime nextRestart)
        {
            Puts($"Current time: {now} UTC");
            Puts($"Available restart times: {string.Join(", ", restartTimes.Select(t => t.ToString(@"hh\:mm")))}");
            Puts($"Next restart scheduled for {nextRestart} UTC");
        }

        private DateTime FindNextRestartTime(DateTime fromTime)
        {
            if (restartTimes.Count == 0)
            {
                throw new InvalidOperationException("No restart times are scheduled.");
            }

            // Obtener todos los tiempos posibles para hoy y mañana
            var possibleTimes = new List<DateTime>();
            DateTime today = fromTime.Date;
            DateTime tomorrow = today.AddDays(1);

            // Agregar todos los tiempos de reinicio para hoy
            foreach (var time in restartTimes)
            {
                var todayTime = today.Add(time);
                if (todayTime > fromTime)
                {
                    possibleTimes.Add(todayTime);
                }
            }

            // Agregar todos los tiempos de reinicio para mañana
            foreach (var time in restartTimes)
            {
                possibleTimes.Add(tomorrow.Add(time));
            }

            // Ordenar los tiempos y tomar el más próximo
            var nextRestart = possibleTimes.OrderBy(t => t).First();

            L
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху