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

FREE EnhancedHammer : 2.0.7 2.0.7

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

namespace Oxide.Plugins
{
    [Info("Enhanced Hammer", "Iv Misticos", "2.0.7")]
    [Description("Upgrade your buildings easily with a hammer")]
    public class EnhancedHammer : CovalencePlugin
    {
        #region Variables

        private static EnhancedHammer _ins;

        private List<BasePlayer> _activePlayers = new List<BasePlayer>();

        private readonly int _maskConstruction = LayerMask.GetMask("Construction");

        private const string PermissionUse = "enhancedhammer.use";
        private const string PermissionFree = "enhancedhammer.free";
        private const string PermissionDowngrade = "enhancedhammer.downgrade";
        private const string PermissionGradeHit = "enhancedhammer.grade.hit";
        private const string PermissionGradeClick = "enhancedhammer.grade.click";
        private const string PermissionGradeBuild = "enhancedhammer.grade.build";

        #endregion

        #region Configuration

        private Configuration _config;

        private class Configuration
        {
            [JsonProperty(PropertyName = "Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public string[] Commands =
            {
                "eh",
                "hammer",
                "up",
                "grade",
                "upgrade"
            };

            [JsonProperty(PropertyName = "Distance From Entity")]
            public float Distance = 5.0f;

            [JsonProperty(PropertyName = "Allow Auto Grade")]
            public bool AutoGrade = true;

            [JsonProperty(PropertyName = "Send Downgrade Disabled Message")]
            public bool DowngradeMessage = true;

            [JsonProperty(PropertyName = "Cancel Default Hammer Hit Behavior")]
            public bool CancelHammerHitDefaultBehavior = true;

            [JsonProperty(PropertyName = "Default Preferences")]
            public PluginData.Preference Preferences = new PluginData.Preference();
        }

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

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

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

        #endregion

        #region Work with 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
        {
            [JsonProperty(PropertyName = "Player Preferences")]
            public Dictionary<string, Preference> Preferences = new Dictionary<string, Preference>();

            [Serializable]
            public class Preference
            {
                [NonSerialized]
                public BasePlayer Player = null;

                [NonSerialized]
                public BuildingGrade.Enum Grade = BuildingGrade.Enum.None;

                [NonSerialized]
                public float GradeStartTime = 0;

                public float DisableIn = 30f;

                public bool AutoGrade = true;

                #region Helpers

                public bool IsEnabled() => Player?.net?.connection != null && !Mathf.Approximately(GradeStartTime, 0) &&
                                           Grade != BuildingGrade.Enum.None;

                public void SetGrade(BuildingGrade.Enum grade)
                {
                    if ((int) grade > (int) BuildingGrade.Enum.TopTier || (int) grade < (int) BuildingGrade.Enum.None)
                        return;

                    if (Grade != grade)
                    {
                        Grade = grade;
                        Player.IPlayer.Message(GetMsg("Grade: Changed", Player.IPlayer.Id).Replace("{grade}", Grade.ToString()));

                        if (Grade == BuildingGrade.Enum.None && _ins._activePlayers.Contains(Player))
                        {
                            _ins._activePlayers.Remove(Player);
                        }
                        else if (!_ins._activePlayers.Contains(Player))
                        {
                            _ins._activePlayers.Add(Player);
                        }

                        if (_ins._activePlayers.Count == 0)
                        {
                            _ins.Unsubscribe(nameof(_ins.OnPlayerInput));
                        }
                        else
                        {
                            _ins.Subscribe(nameof(_ins.OnPlayerInput));
                        }
                    }

                    UpdateGradeTimer();
                }

                private void UpdateGradeTimer()
                {
                    if (Grade == BuildingGrade.Enum.None)
                        GradeStartTime = 0;
                    else
                        GradeStartTime = Time.realtimeSinceStartup;
                    
                    EnhancedController.Instance.RefreshAvailabilityTime();
                }

                public void DoGrade(BuildingBlock block, bool suppressMessages)
                {
                    UpdateGradeTimer();

                    if (Grade == block.grade)
                        return;

                    if ((int) Grade < (int) block.grade && !Player.IPlayer.HasPermission(PermissionDowngrade))
                    {
                        if (!suppressMessages && _ins._config.DowngradeMessage)
                        {
                            Player.IPlayer.Message(GetMsg("Grade: No Downgrade", Player.IPlayer.Id));
                        }

                        return;
                    }

                    if (Player.IsBuildingBlocked(block.transform.position, block.transform.rotation, block.bounds))
                    {
                        if (!suppressMessages)
                        {
                            Player.IPlayer.Message(GetMsg("Grade: Building Blocked", Player.IPlayer.Id));
                        }

                        return;
                    }

                    if ((int) Grade < 0 || (int) Grade >= block.blockDefinition.grades.Length)
                    {
                        // Invalid grade
                        SetGrade(BuildingGrade.Enum.None);
                        return;
                    }

                    if (block.SecondsSinceAttacked <= 30f)
                    {
                        if (!suppressMessages)
                        {
                            Player.IPlayer.Message(GetMsg("Grade: Recently Damaged", Player.IPlayer.Id));
                        }

                        return;
                    }

                    if (!Player.IPlayer.HasPermission(PermissionFree))
                    {
                        foreach (var item in block.blockDefinition.grades[(int) Grade].costToBuild)
                        {
                            if (Player.inventory.GetAmount(item.itemid) >= item.amount)
                                continue;

                            if (!suppressMessages)
                            {
                                Player.IPlayer.Message(GetMsg("Grade: Insufficient Resources", Player.IPlayer.Id));
                            }

                            return;
                        }

                        var items = Pool.GetList<Item>();
                        foreach (var itemAmount in block.blockDefinition.grades[(int) Grade].costToBuild)
                        {
                            Player.inventory.Take(items, itemAmount.itemid, (int) itemAmount.amount);
                            Player.Command("note.inv", itemAmount.itemid, itemAmount.amount * -1f);
                        }

                        foreach (var item in items)
                        {
                            item.Remove();
                        }

                        ItemManager.DoRemoves();
                        Pool.FreeList(ref items);
                    }

                    block.SetGrade(Grade);
                    block.SetHealthToMax();
                    block.StartBeingRotatable();
                    block.SendNetworkUpdate();
                    block.UpdateSkin();
                    block.ResetUpkeepTime();
                    block.GetBuilding()?.Dirty();

                    var prefab = "assets/bundled/prefabs/fx/build/promote_" + Grade.ToString().ToLower() + ".prefab";
                    if (!StringPool.toNumber.ContainsKey(prefab)) // Ignore if it does not exist so that it does not spam client and/or server side
                        return;

                    Effect.server.Run(prefab, block, 0u, Vector3.zero, Vector3.zero);
                }

                public static Preference Get(string id)
                {
                    Preference preference;
                    if (!_ins._data.Preferences.TryGetValue(id, out preference))
                        _ins._data.Preferences[id] = preference = DeepCopy(_ins._config.Preferences);

                    return preference;
                }

                #endregion
            }
        }

        #endregion

        #region Hooks

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                {"Command: No Permission", "You do not have enough permissions for that (enhancedhammer.use)"},
                {"Command: Player Only", "You must be an in-game player to use this command"},
                {"Command: Invalid Grade", "You have entered an invalid grade"},
                {"Command: Timeout", "Current timeout: {timeout}"},
                {"Command: Auto Grade: Enabled", "You have enabled automatic toggle for grading"},
                {"Command: Auto Grade: Disabled", "You have disabled automatic toggle for grading"},
                {"Command: Auto Grade: Force Disabled", "Auto Grade is disabled on this server"},
                {"Command: Syntax", "Grade command syntax:\n" +
                                    "(grade) - Set current grade to a specific value\n" +
                                    "timeout (Time in seconds) - Disable grading in X seconds\n" +
                                    "autograde (True/False) - Toggle automatic grading toggle"},
                {"Grade: Changed", "Current grade: {grade}"},
                {"Grade: No Downgrade", "Downgrading is not allowed on this server"},
                {"Grade: Building Blocked", "You cannot build there"},
                {"Grade: Insufficient Resources", "You cannot afford this upgrade"},
                {"Grade: Recently Damaged", "This entity was recently damaged"}
            }, this);
        }

        private void Init()
        {
            _ins = this;

            permission.RegisterPermission(PermissionUse, this);
            permission.RegisterPermission(PermissionFree, this);
            permission.RegisterPermission(PermissionDowngrade, this);
            permission.RegisterPermission(PermissionGradeHit, this);
            permission.RegisterPermission(PermissionGradeClick, this);
            permission.RegisterPermission(PermissionGradeBuild, this);
            
            if (!_config.AutoGrade)
                Unsubscribe(nameof(OnStructureUpgrade));
            
            LoadData();

            AddCovalenceCommand(_config.Commands, nameof(CommandGrade));
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
                OnPlayerDisconnected(player);
            
            UnityEngine.Object.DestroyImmediate(EnhancedController.Instance);
            
            SaveData();

            _ins = null;
        }

        private void OnServerInitialized()
        {
            new GameObject().AddComponent<EnhancedController>();

            foreach (var player in BasePlayer.activePlayerList)
                OnPlayerConnected(player);
            
            SaveData();
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            PluginData.Preference.Get(player.UserIDString).Player = player;
        }

        private void OnPlayerDisconnected(BasePlayer player)
        {
            PluginData.Preference.Get(player.UserIDString).SetGrade(BuildingGrade.Enum.None);
        }

        private object OnHammerHit(BasePlayer player, HitInfo info)
        {
            if (!CanUse(player.IPlayer, GradingType.Hit))
                return null;

            var prefs = PluginData.Preference.Get(player.UserIDString);
            if (!prefs.IsEnabled())
                return null;

            var block = info.HitEntity as BuildingBlock;
            if (block == null)
                return null;

            prefs.DoGrade(block, false);
            return _config.CancelHammerHitDefaultBehavior ? false : (object) null;
        }

        private void OnEntityBuilt(HeldEntity planner, GameObject gameObject)
        {
            var player = planner.GetOwnerPlayer();
            if (!CanUse(player.IPlayer, GradingType.Build))
                return;

            var prefs = PluginData.Preference.Get(player.UserIDString);
            if (!prefs.IsEnabled())
                return;
            
            var block = gameObject.ToBaseEntity() as BuildingBlock;
            if (block == null)
                return;
            
            prefs.DoGrade(block, false);
        }

        private object OnStructureUpgrade(BuildingBlock block, BasePlayer player, BuildingGrade.Enum grade)
        {
            if (!CanUse(player.IPlayer, GradingType.Use))
                return null;

            var prefs = PluginData.Preference.Get(player.UserIDString);
            if (!prefs.AutoGrade)
                return null;
            
            if (!prefs.IsEnabled() || grade != prefs.Grade)
            {
                // Enable and update grade when disabled or grade is different
                prefs.SetGrade(grade);
            }

            if (prefs.IsEnabled())
            {
                prefs.DoGrade(block, false);
                return true;
            }

            return null;
        }

        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (!_activePlayers.Contains(player) || !input.IsDown(BUTTON.FIRE_PRIMARY) ||
                !CanUse(player.IPlayer, GradingType.Click) || !(player.GetHeldEntity() is Hammer))
                return;

            RaycastHit hit;
            if (!Physics.Raycast(player.eyes.HeadRay(), out hit, _ins._config.Distance, _ins._maskConstruction))
                return;

            var block = hit.GetEntity() as BuildingBlock;
            if (block == null)
                return;

            PluginData.Preference.Get(player.UserIDString).DoGrade(block, true);
        }

        private void OnServerSave() => SaveData();

        #endregion
        
        #region Commands

        private void CommandGrade(IPlayer player, string command, string[] args)
        {
            if (!CanUse(player, GradingType.Use))
            {
                player.Reply(GetMsg("Command: No Permission", player.Id));
                return;
            }

            var basePlayer = player.Object as BasePlayer;
            if (basePlayer == null)
            {
                player.Reply(GetMsg("Command: Player Only", player.Id));
                return;
            }

            var prefs = PluginData.Preference.Get(player.Id);

            switch (args.Length)
            {
                case 1:
                {
                    BuildingGrade.Enum grade;
                    if (!Enum.TryParse(args[0], true, out grade))
                    {
                        player.Reply(GetMsg("Command: Invalid Grade", player.Id));
                        return;
                    }

                    prefs.SetGrade(grade);
                    return;
                }

                case 2:
                {
                    switch (args[0].ToLower())
                    {
                        case "t":
                        case "timeout":
                        {
                            float timeout;
                            if (!float.TryParse(args[1], out timeout))
                                goto syntax;

                            prefs.DisableIn = timeout;
                            player.Reply(GetMsg("Command: Timeout", player.Id).Replace("{timeout}",
                                timeout.ToString(CultureInfo.CurrentCulture)));
                            
                            return;
                        }

                        case "ag":
                        case "autograde":
                        {
                            if (!_config.AutoGrade)
                            {
                                player.Reply(GetMsg("Command: Auto Grade: Force Disabled", player.Id));
                                break;
                            }
                            
                            bool autograde;
                            if (!bool.TryParse(args[1], out autograde))
                                goto syntax;

                            prefs.AutoGrade = autograde;
                            player.Reply(GetMsg("Command: Auto Grade: " + (prefs.AutoGrade ? "Enabled" : "Disabled"),
                                player.Id));

                            return;
                        }

                        default:
                        {
                            goto syntax;
                        }
                    }

                    return;
                }

                default:
                {
                    goto syntax;
                }
            }

            syntax:
            player.Reply(GetMsg("Command: Syntax", player.Id));
        }
        
        #endregion

        #region Controller

        private class EnhancedController : SingletonComponent<EnhancedController>
        {
            private void UpdateAvailability()
            {
                var nextDisableIn = float.NaN;
                var currentTime = Time.realtimeSinceStartup;
                for (var i = _ins._activePlayers.Count - 1; i >= 0; i--)
                {
                    var player = _ins._activePlayers[i];
                    var prefs = PluginData.Preference.Get(player.UserIDString);
                    var disableIn = prefs.GradeStartTime + prefs.DisableIn - currentTime;
                    if (disableIn > 0 && (float.IsNaN(nextDisableIn) || nextDisableIn > disableIn))
                        nextDisableIn = disableIn;

                    if (!Mathf.Approximately(disableIn, 0) && disableIn > 0)
                        continue;

                    prefs.SetGrade(BuildingGrade.Enum.None);
                }

                if (float.IsNaN(nextDisableIn))
                    return;
                
                RefreshAvailabilityTime(nextDisableIn);
            }

            private void RefreshAvailabilityTime(float nextTime)
            {
                if (IsInvoking(UpdateAvailability))
                    CancelInvoke(UpdateAvailability);
                
                Invoke(UpdateAvailability, nextTime);
            }

            public void RefreshAvailabilityTime()
            {
                var nextDisableIn = float.NaN;
                var currentTime = Time.realtimeSinceStartup;
                for (var i = 0; i < _ins._activePlayers.Count; i++)
                {
                    var player = _ins._activePlayers[i];
                    var prefs = PluginData.Preference.Get(player.UserIDString);
                    var disableIn = prefs.GradeStartTime + prefs.DisableIn - currentTime;
                    if (disableIn > 0 && (float.IsNaN(nextDisableIn) || nextDisableIn > disableIn))
                        nextDisableIn = disableIn;
                }

                RefreshAvailabilityTime(nextDisableIn);
            }
        }

        #endregion

        #region Helpers

        private enum GradingType : byte
        {
            Use,
            Hit,
            Click,
            Build
        }

        private static bool CanUse(IPlayer player, GradingType type)
        {
            if (!player.HasPermission(PermissionUse))
                return false;

            switch (type)
            {
                case GradingType.Hit:
                {
                    return player.HasPermission(PermissionGradeHit);
                }

                case GradingType.Click:
                {
                    return player.HasPermission(PermissionGradeClick);
                }

                case GradingType.Build:
                {
                    return player.HasPermission(PermissionGradeBuild);
                }

                default:
                {
                    return true;
                }
            }
        }

        private static string GetMsg(string key, string userId = null) => _ins.lang.GetMessage(key, _ins, userId);

        private static T DeepCopy<T>(T other)
        {
            using (var ms = new MemoryStream())
            {
                var formatter = new BinaryFormatter();

                formatter.Serialize(ms, other);
                ms.Position = 0;

                return (T) formatter.Deserialize(ms);
            }
        }

        #endregion
    }
}

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