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

FREE BuildTools : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("Build Tools", "Puntofila.exe", "1.0.0")]
    public class BuildTools : RustPlugin
    {
        #region Fields

        [PluginReference] private Plugin ImageLibrary, NoEscape, Clans, Friends, Notify, UINotify, RaidZone;

        private static BuildTools _instance;

        private enum Types
        {
            None = -1,
            Remove = 5,
            Wood = 1,
            Stone = 2,
            Metal = 3,
            TopTier = 4
        }

        private const string PermAll = "buildtools.all";
        private const string PermFree = "buildtools.free";

        #endregion

        #region Config

        private static Configuration _config;

        private class Configuration
        {
            [JsonProperty(PropertyName = "Remove Commands")]
            public string[] RemoveCommands = { "remove" };

            [JsonProperty(PropertyName = "Upgrade Commands")]
            public string[] UpgradeCommands = { "up", "building.upgrade" };

            [JsonProperty(PropertyName = "Work with Notify?")]
            public bool UseNotify = true;

            [JsonProperty(PropertyName = "Setting Modes", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<Mode> Modes = new List<Mode>
            {
                new Mode { Type = Types.Remove, Permission = string.Empty },
                new Mode { Type = Types.Wood, Permission = string.Empty },
                new Mode { Type = Types.Stone, Permission = string.Empty },
                new Mode { Type = Types.Metal, Permission = string.Empty },
                new Mode { Type = Types.TopTier, Permission = string.Empty }
            };

            [JsonProperty(PropertyName = "Upgrade Settings")]
            public UpgradeSettings Upgrade = new UpgradeSettings
            {
                ActionTime = 30,
                Cooldown = 0,
                VipCooldown = new Dictionary<string, int>
                {
                    ["buildtool.vip"] = 0,
                    ["buildtool.premium"] = 0
                },
                AfterWipe = 0,
                VipAfterWipe = new Dictionary<string, int>
                {
                    ["buildtool.vip"] = 0,
                    ["buildtool.premium"] = 0
                }
            };

            [JsonProperty(PropertyName = "Remove Settings")]
            public RemoveSettings Remove = new RemoveSettings
            {
                ActionTime = 30,
                Cooldown = 0,
                VipCooldown = new Dictionary<string, int>
                {
                    ["buildtool.vip"] = 0,
                    ["buildtool.premium"] = 0
                },
                AfterWipe = 0,
                VipAfterWipe = new Dictionary<string, int>
                {
                    ["buildtool.vip"] = 0,
                    ["buildtool.premium"] = 0
                },
                Condition = new ConditionSettings
                {
                    Default = true,
                    Percent = false,
                    PercentValue = 0
                },
                ReturnItem = true,
                ReturnPercent = 100,
                BlockedList = new List<string>
                {
                    "shortname 1",
                    "shortname 2",
                    "shortname 3"
                }
            };

            [JsonProperty(PropertyName = "Block Settings")]
            public BlockSettings Block = new BlockSettings
            {
                UseNoEscape = true,
                UseClans = true,
                UseFriends = true,
                UseCupboard = true
            };
        }

        private class ConditionSettings
        {
            [JsonProperty(PropertyName = "Default (from game)")]
            public bool Default;

            [JsonProperty(PropertyName = "Use percent?")]
            public bool Percent;

            [JsonProperty(PropertyName = "Percent (value)")]
            public float PercentValue;
        }

        private class BlockSettings
        {
            [JsonProperty(PropertyName = "Work with NoEscape?")]
            public bool UseNoEscape;

            [JsonProperty(PropertyName = "Work with Clans? (clan members will be able to delete/upgrade)")]
            public bool UseClans;

            [JsonProperty(PropertyName = "Work with Friends? (friends will be able to delete/upgrade)")]
            public bool UseFriends;

            [JsonProperty(PropertyName = "Can those authorized in the cupboard delete/upgrade?")]
            public bool UseCupboard;

            [JsonProperty(PropertyName = "Is an upgrade/remove cupbaord required?")]
            public bool NeedCupboard;
        }

        private abstract class TotalSettings
        {
            [JsonProperty(PropertyName = "Time of action")]
            public int ActionTime;

            [JsonProperty(PropertyName = "Cooldown (default | 0 - disable)")]
            public int Cooldown;

            [JsonProperty(PropertyName = "Cooldowns", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, int> VipCooldown;

            [JsonProperty(PropertyName = "Block After Wipe (default | 0 - disable)")]
            public int AfterWipe;

            [JsonProperty(PropertyName = "Block After Wipe", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, int> VipAfterWipe;

            public int GetCooldown(BasePlayer player)
            {
                int min = Cooldown;
                foreach (var check in VipCooldown)
                {
                    if (player.IPlayer.HasPermission(check.Key) && check.Value < min)
                        min = check.Value;
                }
                return min;
            }

            public int GetWipeCooldown(BasePlayer player)
            {
                int min = AfterWipe;
                foreach (var check in VipAfterWipe)
                {
                    if (player.IPlayer.HasPermission(check.Key) && check.Value < min)
                        min = check.Value;
                }
                return min;
            }
        }

        private class UpgradeSettings : TotalSettings { }

        private class RemoveSettings : TotalSettings
        {
            [JsonProperty(PropertyName = "Blocked items to remove (prefab)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<string> BlockedList;

            [JsonProperty(PropertyName = "Return Item")]
            public bool ReturnItem;

            [JsonProperty(PropertyName = "Returnable Item Percentage")]
            public float ReturnPercent;

            [JsonProperty(PropertyName = "Can friends remove? (Friends)")]
            public bool CanFriends;

            [JsonProperty(PropertyName = "Can clanmates remove? (Clans)")]
            public bool CanClan;

            [JsonProperty(PropertyName = "Can teammates remove?")]
            public bool CanTeams;

            [JsonProperty(PropertyName = "Require a cupboard")]
            public bool RequireCupboard;

            [JsonProperty(PropertyName = "Remove by cupboard? (those who are authorized in the cupboard can remove)")]
            public bool RemoveByCupboard;

            [JsonProperty(PropertyName = "Condition Settings")]
            public ConditionSettings Condition;
        }

        private class Mode
        {
            [JsonProperty(PropertyName = "Type (Remove/Wood/Stone/Metal/TopTier)")]
            [JsonConverter(typeof(StringEnumConverter))]
            public Types Type;

            [JsonProperty(PropertyName = "Permission (ex: buildtools.1)")]
            public string Permission;
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) throw new Exception();
                SaveConfig();
            }
            catch (Exception ex)
            {
                PrintError("Your configuration file contains an error. Using default configuration values.");
                LoadDefaultConfig();
                Debug.LogException(ex);
            }
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(_config);
        }

        protected override void LoadDefaultConfig()
        {
            _config = new Configuration();
        }

        #endregion

        #region Data

        private PluginData _data;

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(Name, _data);
        }

        private void LoadData()
        {
            try
            {
                _data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>(Name);
            }
            catch (Exception e)
            {
                PrintError(e.ToString());
            }

            if (_data == null) _data = new PluginData();
        }

        private class PluginData
        {
            public Dictionary<ulong, PlayerData> Players = new Dictionary<ulong, PlayerData>();
        }

        private class PlayerData
        {
            public DateTime LastUpgrade = new DateTime(1970, 1, 1, 0, 0, 0);
            public DateTime LastRemove = new DateTime(1970, 1, 1, 0, 0, 0);

            public int LeftTime(bool remove, int cooldown)
            {
                DateTime time = remove ? LastRemove : LastUpgrade;
                return (int)time.AddSeconds(cooldown).Subtract(DateTime.UtcNow).TotalSeconds;
            }

            public bool HasCooldown(bool remove, int cooldown)
            {
                DateTime time = remove ? LastRemove : LastUpgrade;
                return DateTime.UtcNow.Subtract(time).TotalSeconds < cooldown;
            }

            public static bool HasWipeCooldown(int cooldown)
            {
                return DateTime.UtcNow.Subtract(SaveRestore.SaveCreatedTime.ToUniversalTime()).TotalSeconds < cooldown;
            }

            public static int WipeLeftTime(int cooldown)
            {
                return (int)SaveRestore.SaveCreatedTime.ToUniversalTime().AddSeconds(cooldown).Subtract(DateTime.UtcNow).TotalSeconds;
            }
        }

        private PlayerData GetPlayerData(ulong userId)
        {
            PlayerData playerData;
            if (!_data.Players.TryGetValue(userId, out playerData))
                _data.Players.Add(userId, playerData = new PlayerData());

            return playerData;
        }

        #endregion

        #region Toast Notifications

        private void ShowToast(BasePlayer player, string text, int type = 0)
        {
            if (player == null || !player.IsConnected) return;
            player.Command("gametip.showtoast", type, text);
        }

        #endregion

        #region Hooks

        private void Init()
        {
            _instance = this;
            LoadData();
            RegisterPermissions();
            AddCovalenceCommand(_config.UpgradeCommands, nameof(CmdUpgrade));
            AddCovalenceCommand(_config.RemoveCommands, nameof(CmdRemove));
        }

        private void Unload()
        {
            BuildComponent[] builds = _components.Values.ToArray();
            foreach (BuildComponent build in builds)
            {
                if (build != null)
                    build.Kill();
            }
            
            SaveData();
            _config = null;
            _instance = null;
        }

        private object OnHammerHit(BasePlayer player, HitInfo info)
        {
            if (player == null || info == null) return null;

            BaseCombatEntity entity = info.HitEntity as BaseCombatEntity;
            if (entity == null || entity.OwnerID == 0) return null;

            BuildComponent build = GetBuild(player);
            if (build == null) return null;

            Mode mode = build.GetMode();
            if (mode == null) return null;

            if (!player.CanBuild())
            {
                SendNotify(player, BuildingBlocked, 1);
                return true;
            }

            if (_config.Block.UseNoEscape && NoEscape != null && NoEscape.IsLoaded && IsRaidBlocked(player))
            {
                SendNotify(player, mode.Type == Types.Remove ? RemoveRaidBlocked : UpgradeRaidBlocked, 1);
                return true;
            }

            BuildingPrivlidge cupboard = entity.GetBuildingPrivilege();
            if (cupboard == null && _config.Block.NeedCupboard)
            {
                SendNotify(player, CupboardRequired, 1);
                return true;
            }

            if (entity.OwnerID != player.userID)
            {
                bool any = (_config.Block.UseFriends && Friends != null && Friends.IsLoaded && IsFriends(player.OwnerID, entity.OwnerID)) ||
                           (_config.Block.UseClans && Clans != null && Clans.IsLoaded && IsClanMember(player.OwnerID, entity.OwnerID)) ||
                           (_config.Block.UseCupboard && (cupboard == null || cupboard.IsAuthed(player)));

                if (!any)
                {
                    SendNotify(player, mode.Type == Types.Remove ? CantRemove : CantUpgrade, 1);
                    return true;
                }
            }

            if (mode.Type == Types.Remove)
            {
                if (_config.Remove.BlockedList.Contains(entity.name) || entity is MiniCopter || entity is BaseBoat)
                {
                    SendNotify(player, CantRemove, 1);
                    return true;
                }
            }
            else
            {
                BuildingBlock block = entity as BuildingBlock;
                if (block != null && (int)block.grade >= (int)mode.Type) return true;
            }

            build.DoIt(entity);
            return true;
        }

        private void OnEntityBuilt(Planner plan, GameObject go)
        {
            BasePlayer player = plan.GetOwnerPlayer();
            if (player == null) return;

            BuildingBlock block = go.ToBaseEntity() as BuildingBlock;
            if (block == null) return;

            BuildComponent build = GetBuild(player);
            if (build == null) return;

            Mode mode = build.GetMode();
            if (mode == null || mode.Type == Types.Remove) return;

            build.DoIt(block);
        }

        #endregion

        #region Commands

        [ConsoleCommand("repairall")]
        private void CmdRepair(ConsoleSystem.Arg args)
        {
            BasePlayer player = args.Player();
            if (player == null) return;
            if (!player.IsAdmin) return;
            
            BuildingPrivlidge cupboard = player.GetBuildingPrivilege();
            if (cupboard == null)
            {
                SendNotify(player, NoCupboard, 1);
                return;
            }
            
            List<BuildingBlock> entities = BaseNetworkable.serverEntities.OfType<BuildingBlock>()
                .Where(x => !(x is BasePlayer) && x.GetBuildingPrivilege() == cupboard).ToList();
            List<AutoTurret> turrets = BaseNetworkable.serverEntities.OfType<AutoTurret>().Where(x => x.GetBuildingPrivilege() == cupboard).ToList();
            List<SamSite> samsites = BaseNetworkable.serverEntities.OfType<SamSite>().Where(x => x.GetBuildingPrivilege() == cupboard).ToList();
            
            if (entities.Count == 0) return;
            
            foreach (BuildingBlock block in entities)
            {
                block.SetHealthToMax();
                block.StartBeingRotatable();
                block.SendNetworkUpdate();
            }
            foreach (AutoTurret turret in turrets)
            {
                turret.SetHealth(1000);
                turret.SendNetworkUpdate();
            }
            foreach (SamSite samsite in samsites)
            {
                samsite.SetHealth(1000);
                samsite.SendNetworkUpdate();
            }
        }

        private void CmdRemove(IPlayer cov, string command, string[] args)
        {
            BasePlayer player = cov.Object as BasePlayer;
            if (player == null) return;

            Mode mode = _config.Modes.Find(x => x.Type == Types.Remove);
            if (mode == null || (!string.IsNullOrEmpty(mode.Permission) && !cov.HasPermission(mode.Permission)))
            {
                SendNotify(player, NoPermission, 1);
                return;
            }

            if (args.Length > 0 && args[0] == "all")
            {
                if (!cov.HasPermission(PermAll))
                {
                    SendNotify(player, NoPermission, 1);
                    return;
                }

                BuildingPrivlidge cupboard = player.GetBuildingPrivilege();
                if (cupboard == null)
                {
                    SendNotify(player, NoCupboard, 1);
                    return;
                }

                PlayerData data = GetPlayerData(player.userID);
                int cooldown = _config.Remove.GetCooldown(player);
                
                if (cooldown > 0 && data.HasCooldown(false, cooldown))
                {
                    SendNotify(player, RemoveCanThrough, 1, data.LeftTime(false, cooldown));
                    return;
                }

                int blockWipe = _config.Remove.GetWipeCooldown(player);
                if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
                {
                    SendNotify(player, RemoveCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
                    return;
                }

                List<BaseCombatEntity> entities = BaseNetworkable.serverEntities.OfType<BaseCombatEntity>()
                    .Where(x => !(x is BasePlayer) && x.GetBuildingPrivilege() == cupboard).ToList();
                    
                if (entities.Count == 0 || entities.Any(x => !CanRemove(player, x))) return;

                ServerMgr.Instance.StartCoroutine(StartRemove(player, entities));
                SendNotify(player, SuccessfullyRemove, 0);
                return;
            }

            AddOrGetBuild(player).Init(mode);
        }

        private void CmdUpgrade(IPlayer cov, string command, string[] args)
        {
            BasePlayer player = cov.Object as BasePlayer;
            if (player == null) return;

            if (args.Length == 0)
            {
                AddOrGetBuild(player).GoNext();
                return;
            }

            switch (args[0])
            {
                case "all":
                {
                    if (!cov.HasPermission(PermAll))
                    {
                        SendNotify(player, NoPermission, 1);
                        return;
                    }

                    Types upgradeType;
                    if (args.Length < 2 || ParseType(args[1], out upgradeType) == Types.None)
                    {
                        cov.Reply($"Error syntax! Use: /{command} {args[0]} [wood/stone/metal/toptier]");
                        return;
                    }

                    BuildingPrivlidge cupboard = player.GetBuildingPrivilege();
                    if (cupboard == null)
                    {
                        SendNotify(player, NoCupboard, 1);
                        return;
                    }

                    if (!player.CanBuild())
                    {
                        SendNotify(player, BuildingBlocked, 1);
                        return;
                    }

                    if (_config.Block.UseNoEscape && NoEscape != null && NoEscape.IsLoaded && IsRaidBlocked(player))
                    {
                        SendNotify(player, UpgradeRaidBlocked, 1);
                        return;
                    }

                    PlayerData data = GetPlayerData(player.userID);
                    int cooldown = _config.Upgrade.GetCooldown(player);
                    
                    if (cooldown > 0 && data.HasCooldown(false, cooldown))
                    {
                        SendNotify(player, UpgradeCanThrough, 1, data.LeftTime(false, cooldown));
                        return;
                    }

                    int blockWipe = _config.Upgrade.GetWipeCooldown(player);
                    if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
                    {
                        SendNotify(player, UpgradeCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
                        return;
                    }

                    BuildingGrade.Enum grade = GetEnum(upgradeType);
                    List<BuildingBlock> buildingBlocks = BaseNetworkable.serverEntities.OfType<BuildingBlock>()
                        .Where(x => x.GetBuildingPrivilege() == cupboard).ToList();
                        
                    if (buildingBlocks.Count == 0) return;

                    if (!cov.HasPermission(PermFree))
                    {
                        if (!CanAffordUpgrade(buildingBlocks, grade, player))
                        {
                            SendNotify(player, NotEnoughResources, 1);
                            return;
                        }
                        PayForUpgrade(buildingBlocks, grade, player);
                    }

                    ServerMgr.Instance.StartCoroutine(StartUpgrade(player, buildingBlocks, grade));
                    SendNotify(player, SuccessfullyUpgrade, 0);
                    break;
                }
                default:
                {
                    Types type;
                    if (ParseType(args[0], out type) != Types.None)
                    {
                        List<Mode> modes = GetPlayerModes(player);
                        if (modes == null) return;

                        Mode mode = modes.Find(x => x.Type == type);
                        if (mode == null || (!string.IsNullOrEmpty(mode.Permission) && !cov.HasPermission(mode.Permission)))
                        {
                            SendNotify(player, NoPermission, 1);
                            return;
                        }

                        BuildComponent build = AddOrGetBuild(player);
                        build.Init(mode);
                    }
                    else
                    {
                        AddOrGetBuild(player).GoNext();
                    }
                    break;
                }
            }
        }

        [ConsoleCommand("UI_Builder")]
        private void CmdConsoleBuilding(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();
            if (player == null || !arg.HasArgs()) return;

            switch (arg.Args[0])
            {
                case "mode":
                {
                    int index;
                    if (!arg.HasArgs(2) || !int.TryParse(arg.Args[1], out index)) return;

                    List<Mode> modes = GetPlayerModes(player);
                    if (modes == null || index >= modes.Count) return;
                    
                    Mode mode = modes[index];
                    if (mode == null) return;

                    AddOrGetBuild(player)?.Init(mode);
                    break;
                }
                case "close":
                {
                    GetBuild(player)?.Kill();
                    break;
                }
            }
        }

        #endregion

        #region Component

        private readonly Dictionary<BasePlayer, BuildComponent> _components = new Dictionary<BasePlayer, BuildComponent>();

        private BuildComponent GetBuild(BasePlayer player)
        {
            BuildComponent build;
            if (_components.TryGetValue(player, out build))
                return build;
            return null;
        }

        private BuildComponent AddOrGetBuild(BasePlayer player)
        {
            BuildComponent build;
            if (_components.TryGetValue(player, out build))
                return build;

            build = player.gameObject.AddComponent<BuildComponent>();
            return build;
        }

        private class BuildComponent : FacepunchBehaviour
        {
            private BasePlayer _player;
            private Mode _mode;
            private float _startTime;
            private bool _started = true;
            private float _cooldown;

            private void Awake()
            {
                _player = GetComponent<BasePlayer>();
                _instance._components[_player] = this;
                enabled = false;
            }

            public void Init(Mode mode)
            {
                if (mode == null)
                    mode = GetPlayerModes(_player).FirstOrDefault();

                _mode = mode;
                _startTime = Time.time;
                _cooldown = _mode.Type == Types.Remove ? _config.Remove.ActionTime : _config.Upgrade.ActionTime;
                enabled = true;
                _started = true;
            }

            private void FixedUpdate()
            {
                if (!_started) return;

                float timeLeft = Time.time - _startTime;
                if (timeLeft > _cooldown)
                {
                    Kill();
                    return;
                }

                int remaining = Mathf.RoundToInt(_startTime + _cooldown - Time.time);
                TimeSpan t = TimeSpan.FromSeconds(remaining);
                
                string action;
                if (_mode.Type == Types.Remove)
                    action = "УДАЛЕНИЕ";
                else
                    action = _instance.Msg(_instance.Msg(_player, $"{_mode.Type}"));
                
                string text = string.Format("{1} сек - {2}", t.Minutes, t.Seconds, action);
                _instance.ShowToast(_player, text, 0);
            }

            public void DoIt(BaseCombatEntity entity)
            {
                if (entity == null) return;

                switch (_mode.Type)
                {
                    case Types.Remove:
                    {
                        if (!CanRemove(_player, entity)) return;

                        PlayerData data = _instance.GetPlayerData(_player.userID);
                        int cooldown = _config.Remove.GetCooldown(_player);
                        
                        if (cooldown > 0 && data.HasCooldown(true, cooldown))
                        {
                            _instance.SendNotify(_player, RemoveCanThrough, 1, data.LeftTime(true, cooldown));
                            return;
                        }

                        int blockWipe = _config.Remove.GetWipeCooldown(_player);
                        if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
                        {
                            _instance.SendNotify(_player, RemoveCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
                            return;
                        }

                        RemoveEntity(_player, entity);
                        data.LastRemove = DateTime.UtcNow;
                        break;
                    }
                    default:
                    {
                        BuildingBlock block = entity as BuildingBlock;
                        if (block == null) return;

                        PlayerData data = _instance.GetPlayerData(_player.userID);
                        int cooldown = _config.Upgrade.GetCooldown(_player);
                        
                        if (cooldown > 0 && data.HasCooldown(false, cooldown))
                        {
                            _instance.SendNotify(_player, UpgradeCanThrough, 1, data.LeftTime(false, cooldown));
                            return;
                        }

                        int blockWipe = _config.Upgrade.GetWipeCooldown(_player);
                        if (blockWipe > 0 && PlayerData.HasWipeCooldown(blockWipe))
                        {
                            _instance.SendNotify(_player, UpgradeCanThrough, 1, PlayerData.WipeLeftTime(blockWipe));
                            return;
                        }

                        BuildingGrade.Enum enumGrade = GetEnum(_mode.Type);
                        ConstructionGrade grade = block.blockDefinition.GetGrade(enumGrade, 0);
                        
                        if (grade == null || !block.CanChangeToGrade(enumGrade, 0, _player) ||
                            Interface.CallHook("OnStructureUpgrade", block, _player, enumGrade) != null ||
                            block.SecondsSinceAttacked < 30.0)
                            return;

                        if (!_player.IPlayer.HasPermission(PermFree))
                        {
                            if (!block.CanAffordUpgrade(enumGrade, 0, _player))
                            {
                                _instance.SendNotify(_player, NotEnoughResources, 0);
                                return;
                            }
                            block.PayForUpgrade(grade, _player);
                        }

                        UpgradeBuildingBlock(block, enumGrade);
                        Effect.server.Run("assets/bundled/prefabs/fx/build/promote_" + enumGrade.ToString().ToLower() + ".prefab", block, 0U, Vector3.zero, Vector3.zero);
                        data.LastUpgrade = DateTime.UtcNow;
                        break;
                    }
                }

                _startTime = Time.time;
            }

            public void GoNext()
            {
                List<Mode> modes = GetPlayerModes(_player);
                if (modes == null) return;

                if (_mode == null)
                {
                    _mode = modes.FindAll(x => x.Type != Types.Remove).FirstOrDefault();
                    Init(_mode);
                    return;
                }

                int i = 0;
                for (; i < modes.Count; i++)
                {
                    if (modes[i] == _mode)
                        break;
                }

                i++;
                _mode = modes.Count <= i ? modes[0] : modes[i];
                Init(_mode);
            }

            public Mode GetMode() => _mode;

            private void OnDestroy()
            {
                CancelInvoke();
                if (_instance != null)
                    _instance._components.Remove(_player);
                Destroy(this);
            }

            public void Kill()
            {
                enabled = false;
                _started = false;
                DestroyImmediate(this);
            }
        }

        #endregion

        #region Utils

        private void RegisterPermissions()
        {
            permission.RegisterPermission(PermAll, this);
            permission.RegisterPermission(PermFree, this);

            foreach (Mode mode in _config.Modes)
            {
                if (!string.IsNullOrEmpty(mode.Permission) && !permission.PermissionExists(mode.Permission))
                    permission.RegisterPermission(mode.Permission, this);
            }
        }

        private static string FixNames(string name)
        {
            switch (name)
            {
                case "wall.external.high.wood": return "wall.external.high";
                case "electric.windmill.small": return "generator.wind.scrap";
                case "graveyardfence": return "wall.graveyard.fence";
                case "coffinstorage": return "coffin.storage";
            }
            return name;
        }

        private static List<Mode> GetPlayerModes(BasePlayer player)
        {
            List<Mode> result = new List<Mode>();
            foreach (Mode mode in _config.Modes)
            {
                if (string.IsNullOrEmpty(mode.Permission) || player.IPlayer.HasPermission(mode.Permission))
                    result.Add(mode);
            }
            return result;
        }

        private bool IsRaidBlocked(BasePlayer player)
        {
            if (RaidZone == null) return false;
            object result = RaidZone.Call("IsBlock", player);
            return result is bool && (bool)result;
        }

        private bool IsClanMember(ulong playerID, ulong targetID)
        {
            if (Clans == null) return false;
            object result = Clans.Call("HasFriend", playerID, targetID);
            return result is bool && (bool)result;
        }

        private bool IsFriends(ulong playerID, ulong friendId)
        {
            if (Friends == null) return false;
            object result = Friends.Call("AreFriends", playerID, friendId);
            return result is bool && (bool)result;
        }

        private static bool IsTeammates(ulong player, ulong friend)
        {
            RelationshipManager.PlayerTeam team = RelationshipManager.ServerInstance.FindPlayersTeam(player);
            return team != null && team.members.Contains(friend);
        }

        private static BuildingGrade.Enum GetEnum(Types type)
        {
            switch (type)
            {
                case Types.Wood: return BuildingGrade.Enum.Wood;
                case Types.Stone: return BuildingGrade.Enum.Stone;
                case Types.Metal: return BuildingGrade.Enum.Metal;
                case Types.TopTier: return BuildingGrade.Enum.TopTier;
                default: return BuildingGrade.Enum.None;
            }
        }

        private static void RemoveEntity(BasePlayer player, BaseCombatEntity entity)
        {
            if (_config.Remove.ReturnItem)
                GiveRefund(entity, player);
            entity.Die();
        }

        private static bool CanRemove(BasePlayer player, BaseEntity entity)
        {
            if (entity.OwnerID == 0)
            {
                _instance.SendNotify(player, CantRemove, 1);
                return false;
            }

            StorageContainer storageContainer = entity.GetComponent<StorageContainer>();
            if (storageContainer != null && storageContainer.inventory.itemList.Count > 0)
            {
                _instance.SendNotify(player, CRStorageNotEmpty, 1);
                return false;
            }

            BaseCombatEntity combat = entity.GetComponent<BaseCombatEntity>();
            if (combat != null && combat.SecondsSinceAttacked < 30f)
            {
                _instance.SendNotify(player, CRDamaged, 1);
                return false;
            }

            if (Interface.Call("CanRemove", player, entity) != null)
            {
                _instance.SendNotify(player, CRBeBlocked, 1);
                return false;
            }

            if (_config.Block.NeedCupboard && entity.GetBuildingPrivilege() == null)
            {
                _instance.SendNotify(player, CRBuildingBlock, 1);
                return false;
            }

            if (_config.Block.UseNoEscape && _instance.NoEscape != null && _instance.NoEscape.IsLoaded && _instance.IsRaidBlocked(player))
            {
                _instance.SendNotify(player, RemoveRaidBlocked, 1);
                return false;
            }

            if (player.userID != entity.OwnerID)
            {
                if (_config.Remove.RemoveByCupboard) return true;
                if (_config.Remove.CanClan && _instance.IsClanMember(player.userID, entity.OwnerID)) return true;
                if (_config.Remove.CanFriends && _instance.IsFriends(player.userID, entity.OwnerID)) return true;
                if (_config.Remove.CanTeams && IsTeammates(player.userID, entity.OwnerID)) return true;

                _instance.SendNotify(player, CRNotAccess, 1);
                return false;
            }

            return true;
        }

        private static void GiveRefund(BaseCombatEntity entity, BasePlayer player)
        {
            string shortPrefabName = Regex.Replace(entity.ShortPrefabName, "\\.deployed|_deployed", "");
            shortPrefabName = FixNames(shortPrefabName);

            Item item = ItemManager.CreateByName(shortPrefabName);
            if (item != null)
            {
                HandleCondition(ref item, player, entity);
                player.inventory.GiveItem(item);
                return;
            }

            List<ItemAmount> buildCost = entity.BuildCost();
            if (buildCost == null) return;

            foreach (ItemAmount value in buildCost)
            {
                int amount = _config.Remove.ReturnPercent < 100
                    ? Convert.ToInt32(value.amount * (_config.Remove.ReturnPercent / 100f))
                    : Convert.ToInt32(value.amount);

                Item x = ItemManager.Create(value.itemDef, amount);
                if (x == null) continue;

                HandleCondition(ref x, player, entity);
                player.GiveItem(x);
            }
        }

        private static void HandleCondition(ref Item item, BasePlayer player, BaseCombatEntity entity)
        {
            if (_config.Remove.Condition.Default && entity.pickup.setConditionFromHealth && item.hasCondition)
                item.conditionNormalized = Mathf.Clamp01(entity.healthFraction - entity.pickup.subtractCondition);

            if (_config.Remove.Condition.Percent)
                item.LoseCondition(item.maxCondition * (_config.Remove.Condition.PercentValue / 100f));
        }

        private static void UpgradeBuildingBlock(BuildingBlock block, BuildingGrade.Enum @enum)
        {
            if (block == null || block.IsDestroyed) return;

            block.SetGrade(@enum);
            block.SetHealthToMax();
            block.StartBeingRotatable();
            block.SendNetworkUpdate();
            block.UpdateSkin();
            block.ResetUpkeepTime();
            block.UpdateSurroundingEntities();
            BuildingManager.server.GetBuilding(block.buildingID)?.Dirty();
        }

        private bool CanAffordUpgrade(List<BuildingBlock> blocks, BuildingGrade.Enum @enum, BasePlayer player)
        {
            foreach (BuildingBlock block in blocks)
            {
                ConstructionGrade grade = block.blockDefinition.GetGrade(@enum, 0);
                if (grade == null) continue;
                foreach (ItemAmount itemAmount in grade.costToBuild)
                {
                    if (player.inventory.GetAmount(itemAmount.itemid) < itemAmount.amount)
                        return false;
                }
            }
            return true;
        }

        private static void PayForUpgrade(List<BuildingBlock> blocks, BuildingGrade.Enum @enum, BasePlayer player)
        {
            List<Item> collect = new List<Item>();

            foreach (BuildingBlock block in blocks)
            {
                ConstructionGrade grade = block.blockDefinition.GetGrade(@enum, 0);
                if (grade == null) continue;
                foreach (ItemAmount itemAmount in grade.costToBuild)
                {
                    player.inventory.Take(collect, itemAmount.itemid, (int)itemAmount.amount);
                    player.Command("note.inv " + itemAmount.itemid + " " + (float)((int)itemAmount.amount * -1.0));
                }
            }

            foreach (Item obj in collect)
                obj.Remove();
        }

        private IEnumerator StartUpgrade(BasePlayer player, List<BuildingBlock> blocks, BuildingGrade.Enum @enum)
        {
            for (int i = 0; i < blocks.Count; i++)
            {
                BuildingBlock block = blocks[i];
                if (block == null || block.IsDestroyed) continue;

                UpgradeBuildingBlock(block, @enum);

                if (i % 10 == 0) yield return CoroutineEx.waitForFixedUpdate;
            }
        }

        private IEnumerator StartRemove(BasePlayer player, List<BaseCombatEntity> entities)
        {
            for (int i = 0; i < entities.Count; i++)
            {
                BaseCombatEntity entity = entities[i];
                if (entity == null || entity.IsDestroyed) continue;

                RemoveEntity(player, entity);

                if (i % 10 == 0) yield return CoroutineEx.waitForFixedUpdate;
            }
        }

        private static Types ParseType(string arg, out Types type)
        {
            Types upgradeType;
            if (Enum.TryParse(arg, true, out upgradeType))
            {
                type = upgradeType;
                return type;
            }

            int value;
            if (int.TryParse(arg, out value) && value > 0 && value < 6)
            {
                type = (Types)value;
                return type;
            }

            type = Types.None;
            return type;
        }

        #endregion

        #region Lang

        private const string
            CRNotAccess = "CRNotAccess",
            CRBuildingBlock = "CRBuildingBlock",
            CRBeBlocked = "CRBeBlocked",
            CRStorageNotEmpty = "CRStorageNotEmpty",
            CRDamaged = "CRDamaged",
            SuccessfullyRemove = "SuccessfullyRemove",
            UpgradeTitle = "UpgradeTitle",
            RemoveTitle = "RemoveTitle",
            UpgradeCanThrough = "UpgradeCanThrough",
            RemoveCanThrough = "RemoveCanThrough",
            NoPermission = "NoPermission",
            SuccessfullyUpgrade = "SuccessfullyUpgrade",
            NoCupboard = "NoCupboard",
            CupboardRequired = "CupboardRequired",
            RemoveRaidBlocked = "RemoveRaidBlocked",
            UpgradeRaidBlocked = "UpgradeRaidBlocked",
            BuildingBlocked = "BuildingBlocked",
            CantUpgrade = "CantUpgrade",
            CantRemove = "CantRemove",
            NotEnoughResources = "NotEnoughResources",
            UpgradeTo = "UpgradeTo";

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                [NotEnoughResources] = "Not enough resources to upgrade!",
                [CantRemove] = "You can remove this entity.",
                [CantUpgrade] = "You cannot upgrade this entity.",
                [BuildingBlocked] = "You are building blocked",
                [UpgradeRaidBlocked] = "You cannot upgrade buildings <color=#81B67A>during a raid!</color>!",
                [RemoveRaidBlocked] = "You cannot upgrade or remove <color=#81B67A>during a raid!</color>!",
                [CupboardRequired] = "A Cupboard is required!",
                [NoCupboard] = "No cupboard found!",
                [SuccessfullyUpgrade] = "You have successfully upgraded a building",
                [NoPermission] = "You do not have permission to use this mode!",
                [UpgradeCanThrough] = "You can upgrade the building in: {0}s",
                [RemoveCanThrough] = "You can remove the building in: {0}s",
                [RemoveTitle] = "Remove",
                [UpgradeTitle] = "Upgrade to {0}",
                [SuccessfullyRemove] = "You have successfully removed a building",
                [CRDamaged] = "Can't remove: Server has disabled damaged objects from being removed.",
                [CRStorageNotEmpty] = "Can't remove: The entity storage is not empty.",
                [CRBeBlocked] = "Can't remove: An external plugin blocked the usage.",
                [CRBuildingBlock] = "Can't remove: Missing cupboard",
                [CRNotAccess] = "Can't remove: You don't have any rights to remove this.",
                [UpgradeTo] = "Upgrade to {0}",
                ["Wood"] = "wood",
                ["Stone"] = "stone",
                ["Metal"] = "metal",
                ["TopTier"] = "HQM"
            }, this);
        }

        private string Msg(string key, string userid = null, params object[] obj)
        {
            return string.Format(lang.GetMessage(key, this, userid), obj);
        }

        private string Msg(BasePlayer player, string key, params object[] obj)
        {
            return string.Format(lang.GetMessage(key, this, player.UserIDString), obj);
        }

        private void Reply(BasePlayer player, string key, params object[] obj)
        {
            player.ChatMessage(Msg(player, key, obj));
        }

        private void SendNotify(BasePlayer player, string key, int type, params object[] obj)
        {
            if (_config.UseNotify && (Notify != null || UINotify != null))
                Interface.Oxide.CallHook("SendNotify", player, type, Msg(player, key, obj));
            else
                Reply(player, key, obj);
        }

        #endregion
    }
}

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