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

FREE WModOnline : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("WModOnline", "wakanda | AI", "1.0.0")]
    [Description("Добавляет фейковых игроков к онлайну сервера")]
    class WModOnline : RustPlugin
    {
        #region Configuration
        
        private Configuration config;
        
        #region Variables
        
        private int currentActiveFakes = 0;
        private int targetFakeCount = 0;
        private Timer fakeAdditionTimer;
        private List<int> randomizedNameIndices = new List<int>();
        
        #endregion
        
        public class Configuration
        {
            [JsonProperty("Динамическое добавление фейковых игроков")]
            public bool DynamicFakePlayersEnabled { get; set; } = true;
            
            [JsonProperty("Правила добавления фейковых игроков по количеству реальных")]
            public List<FakePlayerRule> FakePlayerRules { get; set; } = new List<FakePlayerRule>
            {
                new FakePlayerRule { MinRealPlayers = 1, MaxRealPlayers = 9, FakePlayersToAdd = 3 },
                new FakePlayerRule { MinRealPlayers = 10, MaxRealPlayers = 19, FakePlayersToAdd = 5 },
                new FakePlayerRule { MinRealPlayers = 20, MaxRealPlayers = 999, FakePlayersToAdd = 7 }
            };
            
            [JsonProperty("Постепенное добавление фейков (включить)")]
            public bool GradualAdditionEnabled { get; set; } = true;
            
            [JsonProperty("Интервал добавления фейков (секунды)")]
            public int AdditionIntervalSeconds { get; set; } = 60;
            
            [JsonProperty("Статическое количество фейковых игроков (если динамическое отключено)")]
            public int StaticFakePlayersCount { get; set; } = 3;
            
            [JsonProperty("Максимальный онлайн (реальные + боты)")]
            public int MaxTotalPlayers { get; set; } = 50;
            
            [JsonProperty("Список фейковых ников")]
            public List<string> FakePlayerNames { get; set; } = new List<string>
            {
                "Вова",
                "Коля",
                "Саша",
                "Маша#RUST",
                "бублик"
            };
            
            [JsonProperty("Включить перехват команды players")]
            public bool InterceptPlayersCommand { get; set; } = true;
            
            [JsonProperty("Префикс для фейковых игроков")]
            public string FakePlayerPrefix { get; set; } = "[BOT]";
        }
        
        public class FakePlayerRule
        {
            [JsonProperty("Минимум реальных игроков")]
            public int MinRealPlayers { get; set; }
            
            [JsonProperty("Максимум реальных игроков")]
            public int MaxRealPlayers { get; set; }
            
            [JsonProperty("Количество фейков для добавления")]
            public int FakePlayersToAdd { get; set; }
        }
        
        public class FakePlayerData
        {
            public string Name { get; set; }
            public string SteamID { get; set; }
            public string DisplayName { get; set; }
            public int Ping { get; set; }
        }
        
        protected override void LoadDefaultConfig()
        {
            config = new Configuration();
        }
        
        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null)
                {
                    throw new JsonException();
                }
                
                // Перегенерируем случайные индексы после загрузки конфига
                if (config.FakePlayerNames != null && config.FakePlayerNames.Count > 0)
                {
                    GenerateRandomizedIndices();
                }
            }
            catch
            {
                PrintWarning("Конфигурация повреждена, загружается конфигурация по умолчанию");
                LoadDefaultConfig();
            }
        }
        
        protected override void SaveConfig()
        {
            Config.WriteObject(config);
        }
        
        #endregion
        
        #region Hooks
        
        void OnPlayerConnected(BasePlayer player)
        {
            if (config.DynamicFakePlayersEnabled)
            {
                NextTick(() => {
                    var realPlayerCount = BasePlayer.activePlayerList.Count;
                    var totalBeforeUpdate = realPlayerCount + currentActiveFakes;
                    
                    // Если превышен максимум, убираем ботов
                    if (totalBeforeUpdate > config.MaxTotalPlayers)
                    {
                        var botsToRemove = totalBeforeUpdate - config.MaxTotalPlayers;
                        currentActiveFakes = Math.Max(0, currentActiveFakes - botsToRemove);
                        Puts($"Превышен максимум онлайна.Удалено ботов: {botsToRemove}.Текущее количество ботов: {currentActiveFakes}");
                    }
                    
                    UpdateTargetFakeCount();
                    if (!config.GradualAdditionEnabled)
                    {
                        currentActiveFakes = targetFakeCount;
                        NotifyLogoPlugin();
                    }
                });
            }
        }
        
        void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (config.DynamicFakePlayersEnabled)
            {
                NextTick(() => {
                    UpdateTargetFakeCount();
                    if (!config.GradualAdditionEnabled)
                    {
                        currentActiveFakes = targetFakeCount;
                        NotifyLogoPlugin();
                    }
                });
            }
        }
        
        void Init()
        {
            LoadConfig();
            
            // Генерируем случайные индексы для ников
            GenerateRandomizedIndices();
            
            if (config.DynamicFakePlayersEnabled)
            {
                var maxPossibleFakes = config.FakePlayerRules.Max(x => x.FakePlayersToAdd);
                if (config.FakePlayerNames.Count < maxPossibleFakes)
                {
                    PrintWarning($"Недостаточно ников в конфигурации! Максимально нужно {maxPossibleFakes}, а указано {config.FakePlayerNames.Count}");
                }
            }
            else
            {
                if (config.FakePlayerNames.Count < config.StaticFakePlayersCount)
                {
                    PrintWarning($"Недостаточно ников в конфигурации! Нужно {config.StaticFakePlayersCount}, а указано {config.FakePlayerNames.Count}");
                }
            }
            
            // Запускаем таймер для управления фейковыми игроками
            if (config.DynamicFakePlayersEnabled)
            {
                StartFakePlayersManagement();
            }
        }
        
        void Unload()
        {
            fakeAdditionTimer?.Destroy();
        }
        
        void StartFakePlayersManagement()
        {
            fakeAdditionTimer?.Destroy();
            
            // Обновляем целевое количество фейков
            UpdateTargetFakeCount();
            
            if (config.GradualAdditionEnabled)
            {
                // Запускаем таймер для постепенного добавления/удаления фейков
                fakeAdditionTimer = timer.Every(config.AdditionIntervalSeconds, () => 
                {
                    UpdateTargetFakeCount();
                    AdjustFakePlayersGradually();
                });
            }
            else
            {
                // Мгновенно устанавливаем нужное количество фейков
                currentActiveFakes = targetFakeCount;
            }
        }
        
        void UpdateTargetFakeCount()
        {
            var realPlayerCount = BasePlayer.activePlayerList.Count;
            
            // Если нет реальных игроков, не добавляем ботов
            if (realPlayerCount == 0)
            {
                targetFakeCount = 0;
                return;
            }
            
            // Ищем подходящее правило
            targetFakeCount = 0;
            foreach (var rule in config.FakePlayerRules)
            {
                if (realPlayerCount >= rule.MinRealPlayers && realPlayerCount <= rule.MaxRealPlayers)
                {
                    targetFakeCount = Math.Min(rule.FakePlayersToAdd, config.FakePlayerNames.Count);
                    break;
                }
            }
            
            // Проверяем максимальный лимит
            var currentTotal = realPlayerCount + targetFakeCount;
            if (currentTotal > config.MaxTotalPlayers)
            {
                targetFakeCount = Math.Max(0, config.MaxTotalPlayers - realPlayerCount);
            }
        }
        
        void AdjustFakePlayersGradually()
        {
            var realPlayerCount = BasePlayer.activePlayerList.Count;
            
            // Если нет реальных игроков и есть боты, убираем по одному боту каждый тик
            if (realPlayerCount == 0 && currentActiveFakes > 0)
            {
                currentActiveFakes--;
                Puts($"Нет реальных игроков - удален фейковый игрок.Текущее количество: {currentActiveFakes}/{targetFakeCount}");
            }
            // Обычная логика добавления/удаления ботов
            else if (currentActiveFakes < targetFakeCount)
            {
                currentActiveFakes++;
                Puts($"Добавлен фейковый игрок.Текущее количество: {currentActiveFakes}/{targetFakeCount}");
            }
            else if (currentActiveFakes > targetFakeCount)
            {
                currentActiveFakes--;
                Puts($"Удален фейковый игрок.Текущее количество: {currentActiveFakes}/{targetFakeCount}");
            }
            
            // Уведомляем Logo плагин об обновлении
            NotifyLogoPlugin();
        }
        
        void NotifyLogoPlugin()
        {
            var logoPlugin = plugins.Find("Logo");
            if (logoPlugin != null)
            {
                try
                {
                    logoPlugin.Call("RedrawUI");
                }
                catch
                {
                    // Игнорируем ошибки при вызове Logo плагина
                }
            }
        }
        
        object OnServerCommand(ConsoleSystem.Arg arg)
        {
            if (arg?.cmd?.Name == "players" && config.InterceptPlayersCommand)
            {
                var player = arg.Connection?.player as BasePlayer;
                var realPlayers = BasePlayer.activePlayerList;
                var fakeCount = GetCurrentFakePlayerCount();
                
                PrintToConsole(player, "id                name               ping snap updt posi dist");
                
                foreach (var realPlayer in realPlayers)
                {
                    var ping = realPlayer.net?.connection != null ? Network.Net.sv.GetAveragePing(realPlayer.net.connection) : UnityEngine.Random.Range(15, 100);
                    var snap = 0;
                    var updt = 0;
                    var posi = 0;
                    var dist = 0;
                    
                    var formattedName = FormatPlayerName(realPlayer.displayName);
                    PrintToConsole(player, $"{realPlayer.UserIDString} {formattedName} {ping,4} {snap,4} {updt,4} {posi,4} {dist,4}");
                }
                
                for (int i = 0; i < fakeCount; i++)
                {
                    var fakeName = GetRandomizedFakeName(i);
                    if (!string.IsNullOrEmpty(config.FakePlayerPrefix))
                    {
                        fakeName = $"{config.FakePlayerPrefix} {fakeName}";
                    }

                    var fakeSteamId = GenerateFakeSteamID(i);
                    var ping = UnityEngine.Random.Range(15, 85);
                    var snap = 0;
                    var updt = 0;
                    var posi = 0;
                    var dist = 0;
                    
                    var formattedName = FormatPlayerName(fakeName);
                    PrintToConsole(player, $"{fakeSteamId} {formattedName} {ping,4} {snap,4} {updt,4} {posi,4} {dist,4}");
                }
                
                return true;
            }
            
            return null;
        }
        
        object OnServerInformation(ServerMgr serverMgr)
        {
            return null;
        }
        
        #endregion
        
        #region API Methods
        
        // API метод для получения реального количества игроков
        [HookMethod("GetRealPlayerCount")]
        public int GetRealPlayerCount()
        {
            return BasePlayer.activePlayerList.Count;
        }
        
        // API метод для получения фейкового количества игроков
        [HookMethod("GetFakePlayerCount")]
        public int GetFakePlayerCount()
        {
            return GetCurrentFakePlayerCount();
        }
        
        // Внутренний метод для получения текущего количества фейков
        private int GetCurrentFakePlayerCount()
        {
            if (config.DynamicFakePlayersEnabled)
            {
                return currentActiveFakes;
            }
            else
            {
                var realPlayerCount = BasePlayer.activePlayerList.Count;
                
                // Если нет реальных игроков, не показываем ботов
                if (realPlayerCount == 0)
                {
                    return 0;
                }
                
                var maxPossibleFakes = Math.Min(config.StaticFakePlayersCount, config.FakePlayerNames.Count);
                var maxAllowedTotal = config.MaxTotalPlayers - realPlayerCount;
                
                return Math.Min(maxPossibleFakes, Math.Max(0, maxAllowedTotal));
            }
        }
        
        // API метод для получения общего количества игроков
        [HookMethod("GetTotalPlayerCount")]
        public int GetTotalPlayerCount()
        {
            return GetRealPlayerCount() + GetFakePlayerCount();
        }
        
        // API метод для получения списка фейковых игроков
        [HookMethod("GetFakePlayerNames")]
        public List<string> GetFakePlayerNames()
        {
            var result = new List<string>();
            var fakeCount = GetCurrentFakePlayerCount();
            
            for (int i = 0; i < fakeCount; i++)
            {
                var fakeName = GetRandomizedFakeName(i);
                if (!string.IsNullOrEmpty(config.FakePlayerPrefix))
                {
                    fakeName = $"{config.FakePlayerPrefix} {fakeName}";
                }
                result.Add(fakeName);
            }
            
            return result;
        }
        
        // API метод для получения полных данных фейковых игроков
        [HookMethod("GetFakePlayersData")]
        public List<FakePlayerData> GetFakePlayersData()
        {
            var result = new List<FakePlayerData>();
            var fakeCount = GetCurrentFakePlayerCount();
            
            for (int i = 0; i < fakeCount; i++)
            {
                var baseName = GetRandomizedFakeName(i);
                var displayName = baseName;
                
                if (!string.IsNullOrEmpty(config.FakePlayerPrefix))
                {
                    displayName = $"{config.FakePlayerPrefix} {baseName}";
                }
                
                var fakePlayer = new FakePlayerData
                {
                    Name = baseName,
                    SteamID = GenerateFakeSteamID(i),
                    DisplayName = displayName,
                    Ping = UnityEngine.Random.Range(15, 85)
                };
                
                result.Add(fakePlayer);
            }
            
            return result;
        }
        
        // API метод для получения данных конкретного фейкового игрока по индексу
        [HookMethod("GetFakePlayerData")]
        public FakePlayerData GetFakePlayerData(int index)
        {
            var fakeCount = GetCurrentFakePlayerCount();
            
            if (index < 0 || index >= fakeCount)
                return null;
                
            var baseName = GetRandomizedFakeName(index);
            var displayName = baseName;
            
            if (!string.IsNullOrEmpty(config.FakePlayerPrefix))
            {
                displayName = $"{config.FakePlayerPrefix} {baseName}";
            }
            
            return new FakePlayerData
            {
                Name = baseName,
                SteamID = GenerateFakeSteamID(index),
                DisplayName = displayName,
                Ping = UnityEngine.Random.Range(15, 85)
            };
        }
        
        // API метод для проверки является ли SteamID фейковым
        [HookMethod("IsFakeSteamID")]
        public bool IsFakeSteamID(string steamId)
        {
            var fakeCount = GetCurrentFakePlayerCount();
            
            for (int i = 0; i < fakeCount; i++)
            {
                if (GenerateFakeSteamID(i) == steamId)
                    return true;
            }
            
            return false;
        }
        
        // API метод для получения фейкового игрока по SteamID
        [HookMethod("GetFakePlayerBySteamID")]
        public FakePlayerData GetFakePlayerBySteamID(string steamId)
        {
            var fakeCount = GetCurrentFakePlayerCount();
            
            for (int i = 0; i < fakeCount; i++)
            {
                if (GenerateFakeSteamID(i) == steamId)
                {
                    return GetFakePlayerData(i);
                }
            }
            
            return null;
        }
        
        #endregion
        
        #region Commands
        
        [ChatCommand("wm")]
        void ChatCommandWM(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin)
            {
                SendReply(player, "У вас нет прав для использования этой команды!");
                return;
            }
            
            if (args.Length == 0)
            {
                SendReply(player, "Использование:");
                SendReply(player, "/wm info - Показать информацию о плагине");
                SendReply(player, "/wm list - Показать список фейковых игроков");
                return;
            }
            
            switch (args[0].ToLower())
            {
                case "info":
                    SendReply(player, $"Реальных игроков: {GetRealPlayerCount()}");
                    SendReply(player, $"Фейковых игроков: {GetFakePlayerCount()}");
                    SendReply(player, $"Общий онлайн: {GetTotalPlayerCount()}/{config.MaxTotalPlayers}");
                    SendReply(player, $"Режим: {(config.DynamicFakePlayersEnabled ? "Динамический" : "Статический")}");
                    if (config.DynamicFakePlayersEnabled)
                    {
                        SendReply(player, $"Текущих активных фейков: {currentActiveFakes}/{targetFakeCount}");
                        SendReply(player, $"Постепенное добавление: {(config.GradualAdditionEnabled ? "Включено" : "Отключено")}");
                    }
                    break;
                    
                case "list":
                    var fakePlayersData = GetFakePlayersData();
                    if (fakePlayersData.Count == 0)
                    {
                        SendReply(player, "Нет активных фейковых игроков");
                        return;
                    }
                    
                    SendReply(player, "Список фейковых игроков:");
                    for (int i = 0; i < fakePlayersData.Count; i++)
                    {
                        var fakePlayer = fakePlayersData[i];
                        SendReply(player, $"{i + 1}.{fakePlayer.DisplayName} (ID: {fakePlayer.SteamID})");
                    }
                    break;
                    
                default:
                    SendReply(player, "Неизвестная команда.Используйте /wm для списка команд");
                    break;
            }
        }
        
        #endregion
        
        #region Server Query Hooks
        
        object OnServerQuery()
        {
            var originalMaxPlayers = ConVar.Server.maxplayers;
            var totalPlayers = GetTotalPlayerCount();
            
            return null;
        }
        
        #endregion
        
        #region Helper Methods
        
        void GenerateRandomizedIndices()
        {
            randomizedNameIndices.Clear();
            
            // Создаем список всех индексов
            for (int i = 0; i < config.FakePlayerNames.Count; i++)
            {
                randomizedNameIndices.Add(i);
            }
            
            // Перемешиваем список индексов
            for (int i = 0; i < randomizedNameIndices.Count; i++)
            {
                var randomIndex = UnityEngine.Random.Range(i, randomizedNameIndices.Count);
                var temp = randomizedNameIndices[i];
                randomizedNameIndices[i] = randomizedNameIndices[randomIndex];
                randomizedNameIndices[randomIndex] = temp;
            }
        }
        
        string GetRandomizedFakeName(int index)
        {
            if (randomizedNameIndices.Count == 0 || randomizedNameIndices.Count != config.FakePlayerNames.Count)
            {
                GenerateRandomizedIndices();
            }
            
            if (index >= 0 && index < randomizedNameIndices.Count)
            {
                var nameIndex = randomizedNameIndices[index];
                return config.FakePlayerNames[nameIndex];
            }
            
            return config.FakePlayerNames[index % config.FakePlayerNames.Count];
        }
        
        void PrintToConsole(BasePlayer player, string message)
        {
            if (player != null)
            {
                player.ConsoleMessage(message);
            }
            else
            {
                Puts(message);
            }
        }
        
        string GenerateFakeSteamID(int index)
        {
            var baseId = 76561198000000000L;
            
            // Генерируем более разнообразное смещение, избегая повторяющихся цифр
            var seed = index + 1; // +1 чтобы избежать нулевого индекса
            var offset = 0L;
            
            // Создаем псевдослучайное, но детерминированное смещение
            var random = new System.Random(seed * 12345);
            
            // Генерируем 8-значное число без повторяющихся цифр подряд
            var digits = new List<int>();
            var lastDigit = -1;
            
            for (int i = 0; i < 8; i++)
            {
                int digit;
                do
                {
                    digit = random.Next(1, 10); // От 1 до 9, избегаем 0 в начале
                    if (i > 0 && digit == lastDigit)
                    {
                        // Если цифра повторяется, генерируем другую
                        digit = (digit % 9) + 1;
                        if (digit == lastDigit)
                            digit = (digit % 9) + 1;
                    }
                }
                while (digit == lastDigit);
                
                digits.Add(digit);
                lastDigit = digit;
                offset = offset * 10 + digit;
            }
            
            var fakeSteamId = baseId + offset;
            return fakeSteamId.ToString();
        }
        
        string FormatPlayerName(string name)
        {
            if (name.Length > 14)
            {
                return (name.Substring(0, 14) + "..").PadRight(16);
            }
            
            return name.PadRight(16);
        }
        

        
        #endregion
    }
}

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