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

FREE WipeMovementBlock : 0.0.3 0.0.3

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using UnityEngine;
using Network;

namespace Oxide.Plugins
{
    [Info("Wipe Movement Block", "Volk", "0.0.3")]
    [Description("Блокирует движение игроков на определенное время после вайпа")]
    public class WipeMovementBlock : RustPlugin
    {
        #region Конфигурация

        private Configuration? config;

        private class Configuration
        {
            [JsonProperty("Количество минут блокировки движения после вайпа")]
            public int BlockMinutes = 10;

            [JsonProperty("Разрешить администраторам двигаться во время блокировки")]
            public bool AdminsCanMove = true;
            
            [JsonProperty("Примечание")]
            public string Note = "Все сообщения находятся в локализационных файлах: oxide/data/lang/ru( или en )/WipeMovementBlock";
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null) throw new Exception();
                SaveConfig();
            }
            catch
            {
                PrintError("Конфигурация повреждена! Создание новой конфигурации...");
                LoadDefaultConfig();
            }
        }

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

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

        #endregion

        #region Локализация

        private void LoadMessages()
        {
            // Русские сообщения (Русский язык по умолчанию)
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["BlockMovement"] = "Движение заблокировано на {0} минут после вайпа.",
                ["UnblockMovement"] = "Движение разблокировано! Удачной игры!",
                ["TimeRemaining"] = "Движение будет разблокировано через {0} минут и {1} секунд.",
                ["TestModeEnabled"] = "Тестовый режим активирован! Движение заблокировано на {0} секунд.",
                ["TestCommandUsage"] = "Использование: /testblock <секунды>",
                ["NoPermission"] = "У вас нет разрешения на использование этой команды.",
                ["BlockReset"] = "Блокировка движения была сброшена.",
                ["NoActiveBlock"] = "В данный момент нет активной блокировки движения.",
                ["MovementBlocked"] = "Ваше движение заблокировано!"
            }, this, "ru");
            
            // Английские сообщения (English)
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["BlockMovement"] = "Movement is blocked for {0} minutes after wipe.",
                ["UnblockMovement"] = "Movement has been unblocked! Good luck!",
                ["TimeRemaining"] = "Movement will be unblocked in {0} minutes and {1} seconds.",
                ["TestModeEnabled"] = "Test mode activated! Movement is blocked for {0} seconds.",
                ["TestCommandUsage"] = "Usage: /testblock <seconds>",
                ["NoPermission"] = "You don't have permission to use this command.",
                ["BlockReset"] = "Movement block has been reset.",
                ["NoActiveBlock"] = "There is no active movement block at the moment.",
                ["MovementBlocked"] = "Your movement is blocked!"
            }, this, "en");
        }

        #endregion

        #region Данные

        private bool isBlocked = false;
        private DateTime wipeTime;
        private DateTime unblockTime;
        private Timer? movementBlockTimer;
        private bool isTestMode = false;
        
        // Словарь для хранения начальных позиций игроков
        private Dictionary<ulong, Vector3> playerPositions = new Dictionary<ulong, Vector3>();
        // Интервал проверки движения для телепортации (в секундах)
        private const float MovementCheckInterval = 0.1f;

        #endregion

        #region Hooks

        private void Init()
        {
            LoadMessages();
            permission.RegisterPermission("wipemovementblock.bypass", this);
            permission.RegisterPermission("wipemovementblock.admin", this);
        }

        private void OnServerInitialized()
        {
            wipeTime = DateTime.Now;
            StartMovementBlock();
        }

        private void Unload()
        {
            movementBlockTimer?.Destroy();
        }
        
        // Блокировка передвижения через перехват инпута
        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (!isBlocked || config == null)
                return;

            // Проверка прав на обход блокировки
            if (config.AdminsCanMove && player.IsAdmin)
                return;

            if (permission.UserHasPermission(player.UserIDString, "wipemovementblock.bypass"))
                return;

            // Предотвращаем все действия игрока
            if (input.current != null)
            {
                input.current.buttons = 0; // Блокируем все кнопки
            }
            
            // Телепортируем игрока на сохраненную позицию
            if (playerPositions.TryGetValue(player.userID, out Vector3 savedPosition))
            {
                if (Vector3.Distance(savedPosition, player.transform.position) > 0.1f)
                {
                    player.Teleport(savedPosition);
                    
                    // Показываем редкое сообщение о блокировке
                    if (UnityEngine.Random.Range(0, 20) == 0)
                    {
                        player.ChatMessage(GetMsg("MovementBlocked", player.UserIDString));
                    }
                }
            }
            else
            {
                // Если позиция не сохранена, сохраняем текущую
                playerPositions[player.userID] = player.transform.position;
            }
        }
        
        // Отслеживание подключения игроков
        private void OnPlayerConnected(BasePlayer player)
        {
            // Если блокировка активна, запоминаем позицию
            if (isBlocked && player != null)
            {
                playerPositions[player.userID] = player.transform.position;
                
                // Показываем сообщение о блокировке, если она активна
                if (config != null)
                {
                    TimeSpan remainingTime = unblockTime - DateTime.Now;
                    if (remainingTime.TotalSeconds > 0)
                    {
                        int minutes = (int)remainingTime.TotalMinutes;
                        int seconds = remainingTime.Seconds;
                        player.ChatMessage(string.Format(GetMsg("TimeRemaining", player.UserIDString), minutes, seconds));
                    }
                }
            }
        }
        
        // Отслеживание отключения игроков
        private void OnPlayerDisconnected(BasePlayer player)
        {
            // Удаляем информацию о позиции при отключении
            if (playerPositions.ContainsKey(player.userID))
            {
                playerPositions.Remove(player.userID);
            }
        }
        
        // Предотвращение урона от падения во время блокировки
        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            // Во время блокировки предотвращаем урон от падения
            if (!isBlocked) return;
            
            var player = entity as BasePlayer;
            if (player == null) return;
            
            // Проверка прав на обход блокировки
            if (config?.AdminsCanMove == true && player.IsAdmin)
                return;
                
            if (permission.UserHasPermission(player.UserIDString, "wipemovementblock.bypass"))
                return;
                
            // Если урон от падения - отменяем
            if (info?.damageTypes?.GetMajorityDamageType() == Rust.DamageType.Fall)
            {
                info.damageTypes.Scale(Rust.DamageType.Fall, 0f);
            }
        }

        #endregion

        #region Методы

        private void StartMovementBlock()
        {
            if (config == null) return;
            
            isBlocked = true;
            unblockTime = wipeTime.AddMinutes(config.BlockMinutes);
            
            // Вывод сообщения о блокировке
            foreach (var player in BasePlayer.activePlayerList)
            {
                player.ChatMessage(string.Format(GetMsg("BlockMovement", player.UserIDString), config.BlockMinutes));
                
                // Сохраняем начальную позицию
                playerPositions[player.userID] = player.transform.position;
            }
            
            // Таймер разблокировки
            movementBlockTimer = timer.Once(config.BlockMinutes * 60f, () =>
            {
                isBlocked = false;
                
                // Вывод сообщения о разблокировке
                foreach (var player in BasePlayer.activePlayerList)
                {
                    player.ChatMessage(GetMsg("UnblockMovement", player.UserIDString));
                }
                
                // Очищаем сохраненные позиции
                playerPositions.Clear();
            });
            
            // Периодически информировать игроков о времени разблокировки
            timer.Every(60f, () =>
            {
                if (!isBlocked) return;
                
                TimeSpan remainingTime = unblockTime - DateTime.Now;
                if (remainingTime.TotalSeconds <= 0) return;
                
                int minutes = (int)remainingTime.TotalMinutes;
                int seconds = remainingTime.Seconds;
                
                foreach (var player in BasePlayer.activePlayerList)
                {
                    player.ChatMessage(string.Format(GetMsg("TimeRemaining", player.UserIDString), minutes, seconds));
                }
            });
        }
        
        private void StartTestBlock(int seconds)
        {
            if (config == null) return;
            
            // Останавливаем предыдущий таймер, если он существует
            movementBlockTimer?.Destroy();
            
            isBlocked = true;
            isTestMode = true;
            wipeTime = DateTime.Now;
            unblockTime = wipeTime.AddSeconds(seconds);
            
            // Вывод сообщения о тестовой блокировке
            foreach (var player in BasePlayer.activePlayerList)
            {
                player.ChatMessage(string.Format(GetMsg("TestModeEnabled", player.UserIDString), seconds));
                
                // Сохраняем начальную позицию
                playerPositions[player.userID] = player.transform.position;
            }
            
            // Таймер разблокировки
            movementBlockTimer = timer.Once(seconds, () =>
            {
                isBlocked = false;
                isTestMode = false;
                
                // Вывод сообщения о разблокировке
                foreach (var player in BasePlayer.activePlayerList)
                {
                    player.ChatMessage(GetMsg("UnblockMovement", player.UserIDString));
                }
                
                // Очищаем сохраненные позиции
                playerPositions.Clear();
            });
        }
        
        private bool ResetMovementBlock()
        {
            if (!isBlocked)
                return false;
            
            isBlocked = false;
            isTestMode = false;
            movementBlockTimer?.Destroy();
            movementBlockTimer = null;
            
            // Вывод сообщения о разблокировке
            foreach (var player in BasePlayer.activePlayerList)
            {
                player.ChatMessage(GetMsg("UnblockMovement", player.UserIDString));
            }
            
            // Очищаем сохраненные позиции
            playerPositions.Clear();
            
            return true;
        }

        private string GetMsg(string key, string? userId = null) => lang.GetMessage(key, this, userId);

        #endregion

        #region Команды

        [ChatCommand("blockstatus")]
        private void CmdBlockStatus(BasePlayer player, string command, string[] args)
        {
            if (!isBlocked)
            {
                player.ChatMessage(GetMsg("UnblockMovement", player.UserIDString));
                return;
            }
            
            TimeSpan remainingTime = unblockTime - DateTime.Now;
            if (remainingTime.TotalSeconds <= 0)
            {
                player.ChatMessage(GetMsg("UnblockMovement", player.UserIDString));
                return;
            }
            
            int minutes = (int)remainingTime.TotalMinutes;
            int seconds = remainingTime.Seconds;
            player.ChatMessage(string.Format(GetMsg("TimeRemaining", player.UserIDString), minutes, seconds));
        }
        
        [ChatCommand("testblock")]
        private void CmdTestBlock(BasePlayer player, string command, string[] args)
        {
            // Проверка на права администратора
            if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, "wipemovementblock.admin"))
            {
                player.ChatMessage(GetMsg("NoPermission", player.UserIDString));
                return;
            }
            
            if (args.Length < 1)
            {
                player.ChatMessage(GetMsg("TestCommandUsage", player.UserIDString));
                return;
            }
            
            if (int.TryParse(args[0], out int seconds) && seconds > 0)
            {
                StartTestBlock(seconds);
                Puts($"Игрок {player.displayName} активировал тестовую блокировку движения на {seconds} секунд.");
            }
            else
            {
                player.ChatMessage(GetMsg("TestCommandUsage", player.UserIDString));
            }
        }
        
        [ConsoleCommand("wipemovementblock.test")]
        private void CmdConsoleTestBlock(ConsoleSystem.Arg arg)
        {
            if (!arg.IsAdmin)
                return;
                
            if (arg.Args == null || arg.Args.Length < 1)
            {
                Puts("Использование: wipemovementblock.test <секунды>");
                return;
            }
            
            if (int.TryParse(arg.Args[0], out int seconds) && seconds > 0)
            {
                StartTestBlock(seconds);
                Puts($"Тестовая блокировка движения активирована на {seconds} секунд.");
            }
            else
            {
                Puts("Использование: wipemovementblock.test <секунды>");
            }
        }
        
        [ChatCommand("resetblock")]
        private void CmdResetBlock(BasePlayer player, string command, string[] args)
        {
            // Проверка на права администратора
            if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, "wipemovementblock.admin"))
            {
                player.ChatMessage(GetMsg("NoPermission", player.UserIDString));
                return;
            }
            
            if (ResetMovementBlock())
            {
                player.ChatMessage(GetMsg("BlockReset", player.UserIDString));
                Puts($"Игрок {player.displayName} сбросил блокировку движения.");
            }
            else
            {
                player.ChatMessage(GetMsg("NoActiveBlock", player.UserIDString));
            }
        }
        
        [ConsoleCommand("wipemovementblock.reset")]
        private void CmdConsoleResetBlock(ConsoleSystem.Arg arg)
        {
            if (!arg.IsAdmin)
                return;
                
            if (ResetMovementBlock())
            {
                Puts("Блокировка движения была сброшена.");
            }
            else
            {
                Puts("В данный момент нет активной блокировки движения.");
            }
        }
        
        #endregion
    }
}

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