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

FREE AutoTurretInterference : 1.3.6 1.3.6

Нет прав для скачивания
C#:
/*
 * Copyright © 2025 Scalbox - All rights reserved.
 * Developer: Scalbox - Contact: https://discord.gg/yryp3MjkF8
 *
 * DIGITAL CONTENT COPYRIGHT LICENSE
 *
 * INTELLECTUAL PROPERTY:
 * This digital content is protected by copyright under international and local laws.
 * All rights are reserved and any unauthorized use is prohibited.
 * The content purchased may not be reproduced, distributed, transmitted, or used in any form or by any means
 * without the written permission of the copyright holder, except as required by law.
 *
 * TERMS OF USE:
 * 1. Personal Use: Your purchase of this digital content grants you a non-exclusive, non-transferable, revocable license for personal use. The content may not be shared or distributed to third parties.
 * 2. Limitations: You may not modify, alter, adapt, create derivative works from, sell, or license this content without the written permission of the copyright holder.
 * 3. Backup: You may make one backup copy of the content for your personal use, provided that it is not distributed.
 *
 * WARRANTIES AND RESPONSIBILITIES:
 * The copyright holder makes no warranties regarding the accuracy, completeness or suitability of the content for a particular purpose.
 * In no event shall the copyright holder be liable for any damages arising from the use or inability to use the purchased digital content.
 *
 * PERMISSION REQUESTS:
 * For requests for permission to use or other information, please contact:
 *
 * Scalbox
 * info@scalbox.com
 */
using System.Collections;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using ConVar;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using UnityEngine;
using HarmonyLib;
using Rust;
using Harmony = HarmonyLib.Harmony;
using Physics = UnityEngine.Physics;
using Pool = Facepunch.Pool;
using Quaternion = UnityEngine.Quaternion;
using Vector3 = UnityEngine.Vector3;
//==================================================
//CHANGELOG
//==================================================
//1.3.1     =>      15/07/2025
// - Updated: Compatibility with SentryTurrets plugin.
//1.3.2     =>      15/07/2025
// - Updated: SentryTurrets add interference effect
//1.3.3     =>      15/07/2025
// - Implemented: Compatibility with SentryTurrets plugin
//1.3.4     =>      29/07/2025
// - Improved: High performance improvements
//1.3.5     =>      30/07/2025
// - Fix: Bug fix
//1.3.6     =>      01/08/2025
// - Improved: Speed up interference calculation
namespace Oxide.Plugins {
    [Info("AutoTurretInterference", "Scalbox", "1.3.6")]
    [Description("Change Auto Turret interference & Settings")]
    public class AutoTurretInterference : RustPlugin {
#region Fields
        [PluginReference]
        private Plugin? Clans;
        [PluginReference]
        private Plugin? SentryTurrets;
        private int _serverMaxInterference = Sentry.maxinterference;
        private int _serverInterferenceRadius = (int)Sentry.interferenceradius;
        private readonly Queue<AutoTurret> _interferenceOthersUpdateQueue = new();
        private bool _isProcessingInterferenceOthersUpdate;
        private readonly string _rolePermissionPrefix = $"{nameof(AutoTurretInterference).ToLower()}";
        private const string PermissionAdmin = "autoturretinterference.admin";
        private const string PermissionShowAllowed = "autoturretinterference.show.allowed";
        //Permission - Priority
        private readonly Dictionary<string, int> _requiredPermission = new();
        private enum AutoTurretStatusType {
            All = 0, Active = 1, SwitchedOff = 2, NotConnected = 3, HasInterference = 4, WeaponAmmunition = 5, NoWeapon = 6, NoAmmunition = 7
        }
        private readonly int _statusTypeMin = Enum.GetValues(typeof(AutoTurretStatusType)).Cast<int>().Min();
        private readonly int _statusTypeMax = Enum.GetValues(typeof(AutoTurretStatusType)).Cast<int>().Max();
        private const string AutoTurretItemShortname = "autoturret";
        private const string WiretoolItemShortname = "wiretool";
        private const int MaximumNumberAutoTurretsNoLimits = -1;
        private const int DefaultAutoTurretRotateDegrees = 90;
        private const int DefaultAutoTurretViewingAngleAndTargetScanning = 180;
        private const int DefaultAutoTurretDrawTime = 60;
        private const int DefaultAutoTurretDrawFontSize = 16;
        private const bool DefaultInfiniteAmmo = false;
        private const float DefaultHealth = 1000f;
        private const float DefaultRange = 30f;
        private const float DefaultBulletSpeed = 200f;
        private const float DefaultAimCone = 4f;
        private const float DefaultDamageScale = 1f;
        private const string InterferenceEffect = "assets/prefabs/locks/keypad/effects/lock.code.shock.prefab";
        private readonly Vector3 _sentryTurretInterferenceEffectPosition = new(0f, 1f, 0.5f);
        private const int AutoTurretsPerCoroutine = 1;
        private const int AutoTurretsDestroyedPerCoroutine = 10;
        private const float CoroutineAutoTurretsWait = 0.25F;
        private const float CoroutineAutoTurretsInterferenceHandlerWait = 0.01f;
        private readonly List<Coroutine> _coroutines = new();
        //NetID : Coroutine
        private readonly Dictionary<ulong, Coroutine> _interferenceEffectCoroutines = new();
        //Network ID - Timer
        private Dictionary<ulong, Timer> _entityDrawTimers = new();
        private Configuration _config;
        private Data _data;
        private readonly Dictionary<ulong, RolePermission?> _cachedRolePermission = new();
        private readonly Dictionary<ulong, AutoTurret> _cachedAutoTurrets = new();
        private static readonly Translate.Phrase CurrentActiveAutoTurretsPhrase = new("current_active_auto_turrets_phrase", "You have now {0}/{1} active Auto Turrets.");
        private static readonly Translate.Phrase NearbyAutoTurretsPhrase = new("nearby_auto_turrets_phrase", "You now have {0}/{1} active Auto Turrets within a {2}m Radius of this auto turret location.");
        private const string NoPermissions = "<color=red>You don't have permission to use this command.</color>";
        private const string PlayerNotFound = "<color=red>The player could not be found.</color>";
        private static AutoTurretInterference? self;
        private Harmony _harmony;
#endregion
#region Hook
        void Init() {
            Unsubscribe(nameof(OnPluginLoaded));
            _data = Interface.Oxide.DataFileSystem.ReadObject<Data>(Name);
        }
        private void OnNewSave(string filename) {
            _data.AutoTurretCustomizedData.Clear();
            SaveData();
        }
        private void OnServerInitialized() {
            Subscribe(nameof(OnPluginLoaded));
            CacheAllAutoTurrets();
            //Register all required permissions
            foreach (var rolePermission in _config.RolePermission.OrderBy(x => x.Value.Priority)) {
                _requiredPermission.Add($"{_rolePermissionPrefix}.{rolePermission.Key}", rolePermission.Value.Priority);
            }
            permission.RegisterPermission(PermissionAdmin, this);
            permission.RegisterPermission(PermissionShowAllowed, this);
            foreach (var perm in _requiredPermission) permission.RegisterPermission(perm.Key, this);
            StartHandleInterferenceCoroutine();
            self = this;
            _harmony = new Harmony($"{Name}_Patch_{Version.Major}_{Version.Minor}_{Version.Patch}");
            //Apply patche only if [AutoTurretViewingAngleAndTargetScanning] is different from the default value in all configured roles
            if (_config.RolePermission.Values.Any(rp => rp.AutoTurretViewingAngleAndTargetScanning != DefaultAutoTurretViewingAngleAndTargetScanning && rp.AutoTurretViewingAngleAndTargetScanning is > 0 and <= 360)) {
                Puts("Apply patch AutoTurret.InFiringArc");
                _harmony.Patch(original : AccessTools.Method(typeof(AutoTurret), nameof(AutoTurret.InFiringArc)), prefix : new HarmonyMethod(typeof(AutoTurret_Settings), nameof(AutoTurret_Settings.Prefix_InFiringArc)));
            }
            //Apply patche only if [AutoTurretRotate180Degrees, AutoTurretRotate270Degrees, AutoTurretRotate360Degrees] is different from the default value (false) in all configured roles
            if (_config.RolePermission.Values.Any(rp => rp.AutoTurretRotate180Degrees || rp.AutoTurretRotate270Degrees || rp.AutoTurretRotate360Degrees)) {
                Puts("Apply patch AutoTurret.IdleTick");
                _harmony.Patch(original : AccessTools.Method(typeof(AutoTurret), nameof(AutoTurret.IdleTick)), prefix : new HarmonyMethod(typeof(AutoTurret_Settings), nameof(AutoTurret_Settings.Prefix_IdleTick)));
            }
            SentryTurretsPluginIntegration();
            if (_config.ChatCommand.IsNullOrEmpty()) {
                Puts("Command missing in configuration");
                Interface.Oxide.UnloadPlugin(Name);
                return;
            }
            foreach (var command in _config.ChatCommand) {
                AddCovalenceCommand(command, nameof(CmdHandler));
            }
        }
        private void StartHandleInterferenceCoroutine() {
            _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleInterferenceStartup()));
            if (_config.EnableAutomaticsStartAndStop) _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleAutomaticsStartAndStopOnStartup()));
        }
        private void SentryTurretsPluginIntegration() {
            if (SentryTurrets != null && _config.EnabledSentryTurretsPluginIntegration) {
                var onInterferenceUpdateMethod = AccessTools.Method(SentryTurrets.GetType(), "OnInterferenceUpdate");
                if (onInterferenceUpdateMethod != null) {
                    _harmony.Patch(onInterferenceUpdateMethod, prefix : new HarmonyMethod(typeof(SentryTurretsPlugin_Patch), nameof(SentryTurretsPlugin_Patch.Prefix_OnInterferenceUpdate)) );
                }
                var onNearbyTurretsScanMethod = AccessTools.Method(SentryTurrets.GetType(), "OnNearbyTurretsScan");
                if (onNearbyTurretsScanMethod != null) {
                    _harmony.Patch(onNearbyTurretsScanMethod, prefix : new HarmonyMethod(typeof(SentryTurretsPlugin_Patch), nameof(SentryTurretsPlugin_Patch.Prefix_OnNearbyTurretsScan)) );
                }
                if (onInterferenceUpdateMethod != null || onNearbyTurretsScanMethod != null) Puts("########## SentryTurrets plugin detected! Handling interference updates... ##########");
            }
        }
        private void Unload() {
            ServerMgr.Instance.StartCoroutine(HandleUnload());
            _interferenceOthersUpdateQueue.Clear();
            _isProcessingInterferenceOthersUpdate = false;
            if (!_interferenceEffectCoroutines.IsNullOrEmpty()) {
                foreach (var coroutine in _interferenceEffectCoroutines.Values.Where(c => c != null)) {
                    ServerMgr.Instance.StopCoroutine(coroutine);
                }
            }
            if (!_coroutines.IsNullOrEmpty()) {
                foreach (var coroutine in _coroutines.Where(c => c != null)) {
                    ServerMgr.Instance.StopCoroutine(coroutine);
                }
            }
            if (!_entityDrawTimers.IsNullOrEmpty()) {
                foreach (var drawTimer in _entityDrawTimers.Values.Where(t => t is {
                    Destroyed : false
                }
                )) {
                    drawTimer.Destroy();
                }
            }
            _coroutines.Clear();
            _entityDrawTimers.Clear();
            _cachedRolePermission.Clear();
            _requiredPermission.Clear();
            _cachedAutoTurrets.Clear();
            _harmony.UnpatchAll($"{Name}_Patch_{Version.Major}_{Version.Minor}_{Version.Patch}");
            self = null;
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            _config = Config.ReadObject<Configuration>();
            if (!Equals(_config.VersionNumber, Version)) {
                UpdateConfigValues();
                _config.VersionNumber = Version;
            }
            ReorderRolePermissionsByPriority();
            SaveConfig();
        }
        private void ReorderRolePermissionsByPriority() {
            var orderedRolePermissions = _config.RolePermission .OrderBy(rp => rp.Value.Priority) .ToDictionary(rp => rp.Key, rp => rp.Value);
            _config.RolePermission.Clear();
            foreach (var rolePermission in orderedRolePermissions) {
                _config.RolePermission.Add(rolePermission.Key, rolePermission.Value);
            }
        }
        private void UpdateConfigValues() {
            if (_config.VersionNumber < new VersionNumber(1, 0, 1)) {
                _config.PlayerShowTurretCountInfoMessage = true;
            }
            if (_config.VersionNumber < new VersionNumber(1, 0, 2)) {
                _config.EnableMessageInfo = true;
                _config.ChatCommand = new HashSet<string> {
                    "ati", "autoturretinterference"
                }
                ;
            }
            if (_config.VersionNumber < new VersionNumber(1, 0, 8)) {
                DeleteLangFiles();
            }
            if (_config.VersionNumber < new VersionNumber(1, 1, 1)) {
                _config.AllowCommandsToStartAndStop = false;
                _config.EnableAutomaticsStartAndStop = false;
            }
            if (_config.VersionNumber < new VersionNumber(1, 1, 81)) {
                DeleteLangFiles();
            }
            if (_config.VersionNumber < new VersionNumber(1, 1, 84)) {
                DeleteLangFiles();
            }
            if (_config.VersionNumber < new VersionNumber(1, 1, 88)) {
                DeleteLangFiles();
            }
            if (_config.VersionNumber < new VersionNumber(1, 1, 90)) {
                DeleteLangFiles();
            }
            if (_config.VersionNumber < new VersionNumber(1, 1, 91)) {
                DeleteLangFiles();
            }
            if (_config.VersionNumber < new VersionNumber(1, 2, 0)) {
                Puts("Configuration file is outdated. Updating...");
                foreach (var rolePermission in _config.RolePermission) {
                    var priority = rolePermission.Key.ToLower() switch {
                        "default" => 100, "vip1" => 1, "vip2" => 2, "vip3" => 3, _ => 0
                    }
                    ;
                    if (priority <= 0) continue;
                    rolePermission.Value.Priority = priority;
                }
                SaveConfig();
                Puts("Configuration file updated.");
            }
            if (_config.VersionNumber < new VersionNumber(1, 2, 7)) {
                DeleteLangFiles();
            }
        }
        private void DeleteLangFiles() {
            var langDir = Interface.Oxide.LangDirectory;
            string[] languages = lang.GetLanguages(this);
            foreach (var language in languages) {
                var langFile = Path.Combine(langDir, language, $"{Name}.json");
                if (!File.Exists(langFile)) continue;
                File.Delete(langFile);
                Puts($"########## Delete old lang file: {langFile} ##########");
            }
        }
        protected override void LoadDefaultConfig() {
            _config = Configuration.CreateConfig();
        }
        protected override void SaveConfig() => Config.WriteObject(_config);
        private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, _data);
        private void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem) {
            if (newItem == null || string.IsNullOrEmpty(newItem.info.shortname)) return;
            if (_config.EnableMessageInfo && (newItem.info.shortname.Equals(AutoTurretItemShortname)  /*|| newItem.info.shortname.Equals(WiretoolItemShortname)*/
            )) {
                var sb = new StringBuilder();
                sb.AppendLine(Lang("MessageInfoText", player.UserIDString, _config.ChatCommand.First()));
                if (permission.UserHasPermission(player.UserIDString, PermissionShowAllowed) || permission.UserHasPermission(player.UserIDString, PermissionAdmin)) {
                    sb.AppendLine("----------\n");
                    sb.AppendLine(Lang("Show_Command_Help_Usage", player.UserIDString, _statusTypeMin, _statusTypeMax, _config.ChatCommand.First()));
                }
                player.ChatMessage(sb.ToString());
            }
        }
        //Riapplica le patch per la gestione dell'integrazione con il plugin SentryTurrets, quando viene caricato/ricaricato il plugin SentryTurrets
        private void OnPluginLoaded(Plugin plugin) {
            if (!_config.EnabledSentryTurretsPluginIntegration || plugin != SentryTurrets) return;
            SentryTurretsPluginIntegration();
        }
        private void OnGroupPermissionGranted(string name, string perm) {
            if (!_requiredPermission.ContainsKey(perm)) return;
            _cachedRolePermission.Clear();
            _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleInterferenceStartup()));
        }
        private void OnGroupPermissionRevoked(string name, string perm) {
            if (!_requiredPermission.ContainsKey(perm)) return;
            _cachedRolePermission.Clear();
            _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleInterferenceStartup()));
        }
        private void OnUserPermissionRevoked(string id, string permName) {
            if (!_requiredPermission.ContainsKey(permName)) return;
            if (ulong.TryParse(id, out var steamId)) _cachedRolePermission.Remove(steamId);
            _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleInterferenceStartup()));
        }
        private void OnUserPermissionGranted(string id, string permName) {
            if (!_requiredPermission.ContainsKey(permName)) return;
            if (ulong.TryParse(id, out var steamId)) _cachedRolePermission.Remove(steamId);
            _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleInterferenceStartup()));
        }
        private void OnUserGroupAdded(string id, string groupName) {
            if (!permission.GroupExists(groupName)) return;
            if (!_requiredPermission.Keys.Any(perm => permission.GroupHasPermission(groupName, perm))) return;
            if (ulong.TryParse(id, out var steamId)) _cachedRolePermission.Remove(steamId);
            _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleInterferenceStartup()));
        }
        private void OnUserGroupRemoved(string id, string groupName) {
            if (!permission.GroupExists(groupName)) return;
            if (!_requiredPermission.Keys.Any(perm => permission.GroupHasPermission(groupName, perm))) return;
            if (ulong.TryParse(id, out var steamId)) _cachedRolePermission.Remove(steamId);
            _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleInterferenceStartup()));
        }
        private object? OnInterferenceUpdate(AutoTurret autoTurret) {
            return HandleAutoTurretInterference(autoTurret);
        }
        private object OnInterferenceOthersUpdate(AutoTurret autoTurret) {
            // // TODO vecchio metodo, da rimuovere se il nuovo metodo funziona senza problemi
            // _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleAutoTurretInterferenceOthersUpdate_OLD(autoTurret)));
            if (autoTurret == null) return true;
            _interferenceOthersUpdateQueue.Enqueue(autoTurret);
            if (!_isProcessingInterferenceOthersUpdate) {
                _coroutines.Add(ServerMgr.Instance.StartCoroutine(ProcessInterferenceOthersUpdateQueue()));
            }
            return true;
        }
        private void OnPlayerConnected(BasePlayer player) {
            if (player == null) return;
            HandlePlayerConnection(player, null, false);
        }
        private void OnPlayerDisconnected(BasePlayer player, string reason) {
            if (player == null) return;
            HandlePlayerConnection(player, reason, true);
        }
        private void OnPlayerKicked(BasePlayer player, string reason) {
            if (player == null) return;
            HandlePlayerConnection(player, reason, true);
        }
        private void OnEntitySpawned(AutoTurret autoTurret) {
            if (autoTurret == null) return;
            if (autoTurret.net is {
                ID : {
                    IsValid : true
                }
            }
            ) _cachedAutoTurrets.TryAdd(autoTurret.net.ID.Value, autoTurret);
            if (!autoTurret.OwnerID.IsSteamId()) return;
            var rolePermission = GetCachedRolePermission(autoTurret.OwnerID);
            if (rolePermission is not {
                EnableCustomSettings : true
            }
            ) return;
            UpdateAutoTurretSettings(autoTurret, rolePermission, false);
        }
        private object? OnEntityKill(AutoTurret autoTurret) {
            if (autoTurret == null) return null;
            if (autoTurret.net is {
                ID : {
                    IsValid : true
                }
            }
            ) {
                if (_cachedAutoTurrets.ContainsKey(autoTurret.net.ID.Value)) {
                    if (autoTurret.OwnerID.IsSteamId()) _coroutines.Add(ServerMgr.Instance.StartCoroutine(HandleAutoTurretInterferenceOthersUpdateForAllNearAutoTurrets(autoTurret)));
                    _cachedAutoTurrets.Remove(autoTurret.net.ID.Value);
                }
            }
            if (!autoTurret.OwnerID.IsSteamId()) return null;
            RemoveAutoTurretCustomizationData(autoTurret);
            return null;
        }
        private void OnEntityTakeDamage(BasePlayer entity, HitInfo info) {
            if (info == null || info.Initiator == null) return;
            if (info.Initiator is AutoTurret autoTurret && autoTurret.OwnerID.IsSteamId()) {
                var rolePermission = GetCachedRolePermission(autoTurret.OwnerID);
                info.damageTypes.ScaleAll(rolePermission.DamageScale);
            }
        }
#endregion
#region Core
        private void CacheAllAutoTurrets() {
            foreach (var autoTurret in BaseNetworkable.serverEntities.Where(e => e is AutoTurret).Cast<AutoTurret>()) {
                if (autoTurret.net is {
                    ID : {
                        IsValid : true
                    }
                }
                ) _cachedAutoTurrets.TryAdd(autoTurret.net.ID.Value, autoTurret);
            }
            Puts($"Auto Turret cached: {_cachedAutoTurrets.Count}");
        }
        private static PlayerInfo? FindPlayerInfoBySteamID(ulong steamID) {
            var basePlayer = BasePlayer.allPlayerList.FirstOrDefault(p => p.userID == steamID);
            var serverUser = ServerUsers.Get(steamID);
            return ConvertToPlayerInfo(basePlayer, serverUser);
        }
        private static PlayerInfo? ConvertToPlayerInfo(BasePlayer? basePlayer, ServerUsers.User? serverUser = null) {
            if (basePlayer == null && serverUser == null) return null;
            var playerInfo = new PlayerInfo {
                SteamId = basePlayer != null ? basePlayer.userID : serverUser!.steamid, DisplayName = basePlayer != null ? basePlayer.displayName : serverUser!.username, Transform = basePlayer != null ? basePlayer.transform : null, IsBasePlayer = basePlayer != null, PlayerObject = basePlayer != null ? basePlayer : serverUser
            }
            ;
            return playerInfo;
        }
        private void HandlePlayerConnection(BasePlayer player, string reason, bool isDisconnected) {
            if (!_config.EnableAutomaticsStartAndStop) return;
            if (player == null) return;
            if (!isDisconnected) {
                timer.Once(5f, () => {
                    var autoTurretsStartList = _cachedAutoTurrets.Values .Where(at => IsAutoTurretOwner(at, player.userID)) .Where(at => at.OwnerID.IsSteamId() && at.IsOffline() && !at.HasInterference() && IsAutoTurretPowered(at)) .ToList();
                    _coroutines.Add(ServerMgr.Instance.StartCoroutine(StartAutoTurrets(autoTurretsStartList)));
                }
                );
            }
            else {
                var clanInfo = GetClanInfo(player.userID);
                var playerHasClanTeam = clanInfo != null && !clanInfo.ClanMemberUserIdList.IsNullOrEmpty();
                //Some clan/team members are online, don't turn off the auto turrets
                if (playerHasClanTeam && BasePlayer.activePlayerList.Any(p => !p.UserIDString.Equals(player.UserIDString) && clanInfo != null && clanInfo.ClanMemberUserIdList.Contains(p.UserIDString))) {
                    return;
                }
                var autoTurretsStopList = _cachedAutoTurrets.Values .Where(at => IsAutoTurretOwner(at, player.userID)) .Where(at => at.OwnerID.IsSteamId() && at.IsOn() && at.GetConnectedInputCount() > 0) .ToList();
                _coroutines.Add(ServerMgr.Instance.StartCoroutine(StopAutoTurrets(autoTurretsStopList)));
            }
        }
        private IEnumerator StartAutoTurrets(List<AutoTurret>? autoTurretsList) {
            if (autoTurretsList == null) yield break;
            var count = 0;
            foreach (var autoTurret in autoTurretsList) {
                autoTurret.SetFlag(IOEntity.Flag_HasPower, true);
                autoTurret.SetIsOnline(true);
                if (count % AutoTurretsPerCoroutine == 0) yield return CoroutineEx.waitForSeconds(CoroutineAutoTurretsWait);
                count++;
            }
        }
        private static IEnumerator StopAutoTurrets(List<AutoTurret>? autoTurretsList) {
            if (autoTurretsList == null) yield break;
            var count = 0;
            foreach (var autoTurret in autoTurretsList) {
                autoTurret.SetFlag(IOEntity.Flag_HasPower, false);
                autoTurret.SetIsOnline(false);
                if (count % AutoTurretsPerCoroutine == 0) yield return CoroutineEx.waitForSeconds(CoroutineAutoTurretsWait);
                count++;
            }
        }
        private void CmdHandler(IPlayer ipPlayer, string command, string[] arg) {
            var playerCmdCaller = ipPlayer?.Object as BasePlayer;
            if (playerCmdCaller == null) return;
            if (arg.Length == 0) return;
            var action = arg[0].ToLower();
            var isAdmin = permission.UserHasPermission(playerCmdCaller.UserIDString, PermissionAdmin);
            PlayerInfo? playerToCheck;
            var targetSteamID = 0UL;
            var isSteamID = arg.Length > 1 && ulong.TryParse(arg[1], out targetSteamID);
            switch (action) {
                case "starta" : case "startall" : if (isAdmin || _config.AllowCommandsToStartAndStop) {
                    if (isAdmin && arg.Length > 1 && arg[1] != null) {
                        if (FindPlayerInfoBySteamID(targetSteamID) == null) {
                            PrintToChat(playerCmdCaller, PlayerNotFound);
                            return;
                        }
                    }
                    if (!isAdmin && arg.Length > 1 && arg[1] != null) {
                        playerCmdCaller.ChatMessage(NoPermissions);
                        return;
                    }
                    var autoTurretsStartList = _cachedAutoTurrets.Values  // .Where(at => isAdmin && isSteamID ? at.OwnerID.Equals(targetSteamID) : at.OwnerID.Equals(playerCmdCaller.userID))
                    .Where(at => IsAutoTurretOwner(at, isAdmin && isSteamID ? targetSteamID : playerCmdCaller.userID)) .Where(at => at.OwnerID.IsSteamId() && at.IsOffline() && !at.HasInterference() && IsAutoTurretPowered(at)) .ToList();
                    _coroutines.Add(ServerMgr.Instance.StartCoroutine(StartAutoTurrets(autoTurretsStartList)));
                }
                else playerCmdCaller.ChatMessage(NoPermissions);
                break;
                case "stopa" : case "stopall" : if (isAdmin || _config.AllowCommandsToStartAndStop) {
                    if (isAdmin && arg.Length > 1 && arg[1] != null) {
                        if (FindPlayerInfoBySteamID(targetSteamID) == null) {
                            PrintToChat(playerCmdCaller, PlayerNotFound);
                            return;
                        }
                    }
                    if (!isAdmin && arg.Length > 1 && arg[1] != null) {
                        playerCmdCaller.ChatMessage(NoPermissions);
                        return;
                    }
                    var autoTurretsStopList = _cachedAutoTurrets.Values  // .Where(at => isAdmin && isSteamID ? at.OwnerID.Equals(targetSteamID) : at.OwnerID.Equals(playerCmdCaller.userID))
                    .Where(at => IsAutoTurretOwner(at, isAdmin && isSteamID ? targetSteamID : playerCmdCaller.userID)) .Where(at => at.OwnerID.IsSteamId() && at.IsOn() && at.GetConnectedInputCount() > 0) .ToList();
                    _coroutines.Add(ServerMgr.Instance.StartCoroutine(StopAutoTurrets(autoTurretsStopList)));
                }
                else playerCmdCaller.ChatMessage(NoPermissions);
                break;
                case "start" : if (isAdmin || _config.AllowCommandsToStartAndStop) {
                    if (isAdmin && arg.Length > 1 && arg[1] != null) {
                        if (FindPlayerInfoBySteamID(targetSteamID) == null) {
                            PrintToChat(playerCmdCaller, PlayerNotFound);
                            return;
                        }
                    }
                    if (!isAdmin && arg.Length > 1 && arg[1] != null) {
                        playerCmdCaller.ChatMessage(NoPermissions);
                        return;
                    }
                    var autoTurret = GetPlayerAutoTurretLookingAt(isAdmin && isSteamID ? targetSteamID : playerCmdCaller.userID);
                    if (autoTurret == null) {
                        playerCmdCaller.ChatMessage(Lang("Look_Auto_Turret_For_Start_Error_Message", playerCmdCaller.UserIDString));
                        return;
                    }
                    if (autoTurret.IsOffline() && !autoTurret.HasInterference() && IsAutoTurretPowered(autoTurret)) {
                        _coroutines.Add(ServerMgr.Instance.StartCoroutine(StartAutoTurrets(new List<AutoTurret> {
                            autoTurret
                        }
                        )));
                    }
                    else {
                        playerCmdCaller.ChatMessage(Lang("Power_On_Auto_Turret_Not_Allowed", playerCmdCaller.UserIDString));
                    }
                }
                else playerCmdCaller.ChatMessage(NoPermissions);
                break;
                case "stop" : if (isAdmin || _config.AllowCommandsToStartAndStop) {
                    if (isAdmin && arg.Length > 1 && arg[1] != null) {
                        if (FindPlayerInfoBySteamID(targetSteamID) == null) {
                            PrintToChat(playerCmdCaller, PlayerNotFound);
                            return;
                        }
                    }
                    if (!isAdmin && arg.Length > 1 && arg[1] != null) {
                        playerCmdCaller.ChatMessage(NoPermissions);
                        return;
                    }
                    var autoTurret = GetPlayerAutoTurretLookingAt(isAdmin && isSteamID ? targetSteamID : playerCmdCaller.userID);
                    if (autoTurret == null) {
                        playerCmdCaller.ChatMessage(Lang("Look_Auto_Turret_For_Stop_Error_Message", playerCmdCaller.UserIDString));
                        return;
                    }
                    if (autoTurret.IsOn() && autoTurret.GetConnectedInputCount() > 0) {
                        _coroutines.Add(ServerMgr.Instance.StartCoroutine(StopAutoTurrets(new List<AutoTurret> {
                            autoTurret
                        }
                        )));
                    }
                    else {
                        playerCmdCaller.ChatMessage(Lang("Power_Off_Auto_Turret_Not_Allowed", playerCmdCaller.UserIDString));
                    }
                }
                else playerCmdCaller.ChatMessage(NoPermissions);
                break;
                case "st" : case "status" : if (isAdmin && isSteamID) {
                    playerToCheck = FindPlayerInfoBySteamID(targetSteamID);
                    if (playerToCheck == null) {
                        PrintToChat(playerCmdCaller, PlayerNotFound);
                        return;
                    }
                    PrintAutoTurretStatistics(playerCmdCaller, playerToCheck);
                    return;
                }
                PrintAutoTurretStatistics(playerCmdCaller, ConvertToPlayerInfo(playerCmdCaller)!);
                break;
                case "sh" : case "show" : if (!permission.UserHasPermission(playerCmdCaller.UserIDString, PermissionShowAllowed) && !isAdmin) {
                    playerCmdCaller.ChatMessage(NoPermissions);
                    return;
                }
                if (arg.Length == 1) {
                    var sb = new StringBuilder();
                    sb.AppendLine(Lang("Show_Command_Help_Usage", playerCmdCaller.UserIDString, _statusTypeMin, _statusTypeMax, _config.ChatCommand.First()));
                    for (var i = _statusTypeMin; i <= _statusTypeMax; i++) {
                        var atst = (AutoTurretStatusType)i;
                        sb.AppendLine($"<color=#4A95CC>/{_config.ChatCommand.First()} show {i}</color> - <color={GetColorByAutoTurretStatusType(atst, true)}>{GetTextByAutoTurretStatusType(playerCmdCaller, atst)}</color>\n");
                    }
                    playerCmdCaller.ChatMessage(sb.ToString());
                    return;
                }
                var statusTypeID = 0;
                //show - status type
                if (arg.Length == 2) {
                    if (!int.TryParse(arg[1], out statusTypeID)) {
                        playerCmdCaller.ChatMessage(Lang("Invalid_Show_Type", playerCmdCaller.UserIDString));
                        return;
                    }
                    targetSteamID = 0UL;
                    isSteamID = false;
                }
                //show - status type - steamID
                if (arg.Length == 3) {
                    if (!int.TryParse(arg[1], out statusTypeID)) {
                        playerCmdCaller.ChatMessage(Lang("Invalid_Show_Type", playerCmdCaller.UserIDString));
                        return;
                    }
                    isSteamID = arg.Length > 1 && ulong.TryParse(arg[2], out targetSteamID);
                    if (!isSteamID) {
                        playerCmdCaller.ChatMessage(Lang("Invalid_SteamID", playerCmdCaller.UserIDString));
                        return;
                    }
                }
                if (!Enum.IsDefined(typeof(AutoTurretStatusType), statusTypeID)) {
                    playerCmdCaller.ChatMessage(Lang("Invalid_Show_Type_Value", playerCmdCaller.UserIDString, _statusTypeMin, _statusTypeMax));
                    return;
                }
                var statusTypeEnum = (AutoTurretStatusType)statusTypeID;
                if (isAdmin && isSteamID) playerToCheck = FindPlayerInfoBySteamID(targetSteamID);
                else playerToCheck = FindPlayerInfoBySteamID(playerCmdCaller.userID);
                if (playerToCheck == null) {
                    PrintToChat(playerCmdCaller, PlayerNotFound);
                    return;
                }
                var playerAllAutoTurrets = PlayerClanAllAutoTurrets(playerToCheck);
                if (playerAllAutoTurrets.IsNullOrEmpty()) {
                    playerAllAutoTurrets = PlayerAllAutoTurrets(playerToCheck);
                }
                if (playerAllAutoTurrets.IsNullOrEmpty()) {
                    playerCmdCaller.ChatMessage(Lang("No_Auto_Turrets_Found", playerCmdCaller.UserIDString));
                    return;
                }
                if (statusTypeEnum == AutoTurretStatusType.All) {
                    foreach (AutoTurretStatusType autoTurretsStatusType in Enum.GetValues(typeof(AutoTurretStatusType))) {
                        if (autoTurretsStatusType is AutoTurretStatusType.All or AutoTurretStatusType.WeaponAmmunition or AutoTurretStatusType.NoWeapon or AutoTurretStatusType.NoAmmunition) continue;
                        AutoTurretFilterByStatusType(playerAllAutoTurrets, autoTurretsStatusType) .ForEach(at => DrawText(playerCmdCaller, at, autoTurretsStatusType));
                    }
                }
                else AutoTurretFilterByStatusType(playerAllAutoTurrets, statusTypeEnum).ForEach(at => DrawText(playerCmdCaller, at, statusTypeEnum));
                break;
            }
        }
        private static List<AutoTurret> AutoTurretFilterByStatusType(List<AutoTurret> autoTurrets, AutoTurretStatusType autoTurretStatusType) {
            if (autoTurrets.IsNullOrEmpty()) return new List<AutoTurret>();
            return autoTurretStatusType switch {
                AutoTurretStatusType.Active => autoTurrets.Where(at => at.IsOn() && !at.HasInterference()).ToList(), AutoTurretStatusType.SwitchedOff => autoTurrets.Where(at => !at.IsOn() && at.GetConnectedInputCount() > 0).ToList(), AutoTurretStatusType.NotConnected => autoTurrets.Where(at => !at.IsOn() && at.GetConnectedInputCount().Equals(0)).ToList(), AutoTurretStatusType.HasInterference => autoTurrets.Where(at => at.HasInterference()).ToList(), AutoTurretStatusType.WeaponAmmunition => autoTurrets.ToList(), AutoTurretStatusType.NoWeapon => autoTurrets.Where(at => at.GetAttachedWeapon() == null).ToList(), AutoTurretStatusType.NoAmmunition => autoTurrets.Where(at => at.GetAttachedWeapon() != null && at.GetAttachedWeapon().primaryMagazine.contents == 0).ToList(), _ => autoTurrets
            }
            ;
        }
        private static string GetColorByAutoTurretStatusType(AutoTurretStatusType autoTurretStatusType, bool hexMode = false) {
            return autoTurretStatusType switch {
                AutoTurretStatusType.Active => !hexMode ? "0,1,0" : "#00FF00", AutoTurretStatusType.SwitchedOff => !hexMode ? "1,0.984,0" : "#FFFB00", AutoTurretStatusType.NotConnected => !hexMode ? "1,0.592,0" : "#FF9700", AutoTurretStatusType.HasInterference => !hexMode ? "1,0,0" : "#FF0000", AutoTurretStatusType.WeaponAmmunition => !hexMode ? "0,1,0" : "#00FF00", AutoTurretStatusType.NoWeapon => !hexMode ? "1,0,0" : "#FF0000", AutoTurretStatusType.NoAmmunition => !hexMode ? "1,0,0" : "#FF0000", _ => !hexMode ? "0.29,0.584,0.8" : "#4A95CC"
            }
            ;
        }
        private string GetTextByAutoTurretStatusType(BasePlayer player, AutoTurretStatusType autoTurretStatusType) {
            return autoTurretStatusType switch {
                AutoTurretStatusType.Active => Lang("Status_Active", player.UserIDString), AutoTurretStatusType.SwitchedOff => Lang("Status_Switched_Off", player.UserIDString), AutoTurretStatusType.NotConnected => Lang("Status_Not_Connected", player.UserIDString), AutoTurretStatusType.HasInterference => Lang("Status_HasInterference", player.UserIDString), AutoTurretStatusType.WeaponAmmunition => Lang("Status_Weapon_Ammunition_Text", player.UserIDString), AutoTurretStatusType.NoWeapon => Lang("Status_No_Weapon_Text", player.UserIDString), AutoTurretStatusType.NoAmmunition => Lang("Status_No_Ammunition_Text", player.UserIDString), _ => Lang("Show_All_Status", player.UserIDString)
            }
            ;
        }
        private void DrawText(BasePlayer player, AutoTurret? autoTurret, AutoTurretStatusType autoTurretStatusType) {
            if (player == null || autoTurret == null) return;
            if (_entityDrawTimers.ContainsKey(autoTurret.net.ID.Value)) {
                if (!_entityDrawTimers[autoTurret.net.ID.Value].Destroyed) _entityDrawTimers[autoTurret.net.ID.Value].Destroy();
                _entityDrawTimers.Remove(autoTurret.net.ID.Value);
            }
            var drawTimer = timer.Repeat(1f, _config.AutoTurretDrawTime, () => {
                RunCommandAsAdmin(player, () => {
                    var position = autoTurret.transform.position;
                    if (autoTurretStatusType is not (AutoTurretStatusType.WeaponAmmunition or AutoTurretStatusType.NoWeapon or AutoTurretStatusType.NoAmmunition)) player.SendConsoleCommand("ddraw.text", 1, GetColorByAutoTurretStatusType(autoTurretStatusType), position + Vector3.up * 1.20f, $"<size={_config.AutoTurretDrawFontSize}>{GetTextByAutoTurretStatusType(player, autoTurretStatusType)}</size>");
                    if (autoTurretStatusType is AutoTurretStatusType.WeaponAmmunition or AutoTurretStatusType.NoWeapon or AutoTurretStatusType.NoAmmunition) {
                        var attachedWeapon = autoTurret.GetAttachedWeapon();
                        if (attachedWeapon == null) {
                            if (autoTurretStatusType is AutoTurretStatusType.NoWeapon or AutoTurretStatusType.NoAmmunition) player.SendConsoleCommand("ddraw.text", 1, Color.red, autoTurret.transform.position + Vector3.up * 1.20f, $"<size={_config.AutoTurretDrawFontSize}>{GetTextByAutoTurretStatusType(player, autoTurretStatusType)}</size>");
                            return;
                        }
                        if (autoTurretStatusType != AutoTurretStatusType.WeaponAmmunition) return;
                        var autoTurretInventoryWeapon = autoTurret.inventory.itemList.FirstOrDefault(i => i.info.category == ItemCategory.Weapon);
                        var autoTurretInventoryAmmunition = autoTurret.inventory.itemList.Where(i => i.info.category == ItemCategory.Ammunition).ToList();
                        var weaponName = autoTurretInventoryWeapon != null ? autoTurretInventoryWeapon.info.displayName.english : "No weapon";
                        var ammunitionName = autoTurretInventoryAmmunition.FirstOrDefault()?.info.displayName.english ?? "No ammunition";
                        var ammunitionCount = autoTurretInventoryAmmunition.Sum(i => i?.amount ?? 0);
                        ammunitionCount += attachedWeapon.primaryMagazine.contents;
                        if (ammunitionCount == 0 || autoTurretStatusType == AutoTurretStatusType.NoAmmunition) {
                            player.SendConsoleCommand("ddraw.text", 1, Color.red, autoTurret.transform.position + Vector3.up * 1.30f, $"<size={_config.AutoTurretDrawFontSize}>{GetTextByAutoTurretStatusType(player, AutoTurretStatusType.NoAmmunition)}</size>");
                            return;
                        }
                        var finalWeaponText = $"<color=white>{Lang("Status_Weapon_Label", player.UserIDString)}:</color> <color=#FFFB00>{weaponName}</color>";
                        var finalAmmunitionText = $"<color=white>{Lang("Status_Ammunition_Label", player.UserIDString)}:</color> <color=#FFFB00>{ammunitionName}</color> - <color=#00FF00>{ammunitionCount}</color>";
                        player.SendConsoleCommand("ddraw.text", 1, Color.clear, autoTurret.transform.position + Vector3.up * 1.20f, $"<size={_config.AutoTurretDrawFontSize}>{finalWeaponText} - {finalAmmunitionText}</size>");
                    }
                }
                );
            }
            );
            _entityDrawTimers.Add(autoTurret.net.ID.Value, drawTimer);
        }
        private void PrintAutoTurretStatistics(BasePlayer playerCmdCaller, PlayerInfo? playerToCheck, bool isRcon = false) {
            if (playerCmdCaller == null || playerToCheck == null) return;
            var rolePermission = GetCachedRolePermission(playerToCheck.SteamId);
            var playerAllAutoTurrets = PlayerAllAutoTurrets(playerToCheck);
            var playerAutoTurretsNearby = AutoTurretsNearby(playerToCheck, rolePermission.PlayerMaxInterferenceRadius);
            var playerClanAllAutoTurrets = PlayerClanAllAutoTurrets(playerToCheck);
            var sb = new StringBuilder();
            sb.AppendLine(Lang("Stats_Header_Start", playerCmdCaller.UserIDString));
            sb.AppendLine(Lang("Stats_Player_Info", playerCmdCaller.UserIDString, playerToCheck.DisplayName));
            // sb.AppendLine(Lang("Stats_Player_Info", playerCmdCaller.UserIDString, playerToCheck.displayName,
            //     !playerToCheck.net.connection.info.GetBool("global.streamermode")
            //         ? playerToCheck.userID
            //         : "***********"));
            sb.AppendLine(Lang("Stats_Player_At_Total", playerCmdCaller.UserIDString, playerAllAutoTurrets.Count));
            sb.AppendLine(Lang("Stats_Player_At_Active", playerCmdCaller.UserIDString, playerAllAutoTurrets.Count(at => at.IsOn() && !at.HasInterference())));
            sb.AppendLine(Lang("Stats_Player_At_Switched_Off", playerCmdCaller.UserIDString, playerAllAutoTurrets.Count(at => !at.IsOn() && at.GetConnectedInputCount() > 0)));
            sb.AppendLine(Lang("Stats_Player_At_Not_Connected", playerCmdCaller.UserIDString, playerAllAutoTurrets.Count(at => !at.IsOn() && at.GetConnectedInputCount().Equals(0))));
            sb.AppendLine(Lang("Stats_Player_At_HasInterference", playerCmdCaller.UserIDString, playerAllAutoTurrets.Count(at => at.HasInterference())));
            if (playerToCheck.Transform != null) {
                sb.AppendLine("----------");
                sb.AppendLine(Lang("Stats_Player_At_Nearby_Active", playerCmdCaller.UserIDString, playerAutoTurretsNearby.Count(at => at.IsOn() && !at.HasInterference()).ToString()));
            }
            sb.AppendLine("--------------------");
            if (!playerClanAllAutoTurrets.IsNullOrEmpty()) {
                sb.AppendLine(Lang("Stats_Clan", playerCmdCaller.UserIDString));
                sb.AppendLine(Lang("Stats_Clan_At_Total", playerCmdCaller.UserIDString, playerClanAllAutoTurrets.Count));
                sb.AppendLine(Lang("Stats_Clan_At_Active", playerCmdCaller.UserIDString, playerClanAllAutoTurrets.Count(at => at.IsOn() && !at.HasInterference())));
                sb.AppendLine(Lang("Stats_Clan_At_Switched_Off", playerCmdCaller.UserIDString, playerClanAllAutoTurrets.Count(at => !at.IsOn() && at.GetConnectedInputCount() > 0)));
                sb.AppendLine(Lang("Stats_Clan_At_Not_Connected", playerCmdCaller.UserIDString, playerClanAllAutoTurrets.Count(at => !at.IsOn() && at.GetConnectedInputCount().Equals(0))));
                sb.AppendLine(Lang("Stats_Clan_At_HasInterference", playerCmdCaller.UserIDString, playerClanAllAutoTurrets.Count(at => at.HasInterference())));
                sb.AppendLine("--------------------");
            }
            sb.AppendLine(Lang("Stats_Player_Settings", playerCmdCaller.UserIDString));
            sb.AppendLine(Lang("Stats_Player_Settings_At_Limits", playerCmdCaller.UserIDString, rolePermission.PlayerNoInterferenceLimits));
            sb.AppendLine(Lang("Stats_Player_Settings_At_Radius", playerCm
// ... [Code preview truncated due to length. Full source in attached file] ...

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