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

FREE AdvancedStatus : 0.1.17 0.1.17

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6

/*
*  < ----- End-User License Agreement ----->
*  
*  You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of this software without the developer’s consent.*
*  THIS SOFTWARE IS PROVIDED BY IIIaKa AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
*  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*
*  Developer: IIIaKa
*      https://t.me/iiiaka
*      Discord: @iiiaka
*      https://github.com/IIIaKa
*      https://umod.org/user/IIIaKa
*      https://codefling.com/iiiaka
*      https://lone.design/vendor/iiiaka/
*      https://www.patreon.com/iiiaka
*      https://boosty.to/iiiaka
*  Codefling plugin page: https://codefling.com/plugins/advanced-status
*  Codefling license: https://codefling.com/plugins/advanced-status?tab=downloads_field_4
*  
*  Lone.Design plugin page: https://lone.design/product/advanced-status/
*
*  Copyright © 2023-2024 IIIaKa
*/
using System;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Network;
using UnityEngine.Networking;
using Oxide.Core.Libraries.Covalence;
namespace Oxide.Plugins {
    [Info("Advanced Status", "IIIaKa", "0.1.17")]
    [Description("Useful API plugin that imitates in-game status bars, allowing the addition of custom status bars.")]
    class AdvancedStatus : RustPlugin {
        [PluginReference]
        private Plugin ImageLibrary;
#region ~Variables~
        private static AdvancedStatus Instance {
            get;
            set;
        }
        private bool _isReady = false;
        private const string PERMISSION_ADMIN = "advancedstatus.admin", AdvancedStatusName = "AdvancedStatus", GetImage = "GetImage", NoteInv = "note.inv", ImagesPath = $"{AdvancedStatusName}/Images", ImagesPattern = "*.png", Hooks_OnLoaded = $"On{AdvancedStatusName}Loaded", Hooks_OnBarDeleted = "OnAdvancedBarDeleted", Hooks_GainedBuilding = "OnPlayerGainedBuildingPrivilege", Hooks_LostBuilding = "OnPlayerLostBuildingPrivilege", Placeholders_UserId = "*userId*", Placeholders_UserName = "*userName*";
        private readonly string[] HttpScheme = new string[2] {
            "http://", "https://"
        }
        ;
        private string ImagePath = string.Empty;
        public Hash<ulong, PlayerWatcher> _playersList = new Hash<ulong, PlayerWatcher>();
        public Dictionary<string, string> _imagesList = new Dictionary<string, string>();
        public string[] _cachedBarsContainer = new string[25];
        private readonly HashSet<ItemCategory> _excludedBuildingItemCategories = new HashSet<ItemCategory> {
            ItemCategory.Weapon, ItemCategory.Attire, ItemCategory.Medical, ItemCategory.Ammunition, ItemCategory.Component
        }
        ;
        private readonly HashSet<ItemCategory> _buildingBlockItemCategories = new HashSet<ItemCategory> {
            ItemCategory.Construction, ItemCategory.Traps
        }
        ;
        private readonly HashSet<ItemCategory> _buildingBlockItemCategories2 = new HashSet<ItemCategory> {
            ItemCategory.Resources, ItemCategory.Tool, ItemCategory.Food, ItemCategory.Misc
        }
        ;
        private readonly HashSet<int> _exceptionBuildingItems = new HashSet<int>() {
            613961768, 696029452, -144417939, 363163265, -144513264, -566907190, -2124352573, -1379036069, 476066818, -912398867, 1523403414, -1530414568, -1049881973, -1961560162, -979951147, -583379016, 1234878710, 1784406797, 273172220, 576509618, -2107018088, 204970153, 1094293920
        }
        ;
        private readonly HashSet<int> _buildingBlockItems = new HashSet<int>() {
            634478325, 200773292, 1803831286, 122783240, 1911552868, 838831151, 803954639, -1305326964, -1776128552, 2133269020, 830839496, 1533551194, -992286106, 390728933, -520133715, -778875547, 998894949, -886280491, -237809779, 1512054436, -2084071424, 1898094925, -1511285251, 573676040, 1242522330, -1973785141, -695124222, 282103175, 809199956, -1679267738, -489848205, -173268132, -173268125, -173268126, -173268131, -173268129, -173268128, -2058362263, 1358643074, 1885488976, 2104517339, 699075597
        }
        ;
        private readonly HashSet<int> _stackableItems = new HashSet<int>() {
            1055319033, 349762871, 915408809, -1023065463, -1234735557, 215754713, 14241751, 588596902, -2097376851, 785728077, 51984655, -1691396643, -1211166256, -1321651331, 605467368, 1712070256, -1685290200, -1036635990, -727717969, -1800345240, -1671551935, -1199897169, -1199897172, -1023374709, 1553078977, 1401987718, -89874794, -493159321, 1072924620, 1330084809, 926800282, -1802083073, 479143914, 1882709339, 95950017, 1199391518, 1414245522, 1234880403, -1994909036, -1021495308, 642482233, 2019042823, 73681876, 1744298439, 1324203999, -656349006, -7270019, -379734527, -1553999294, -280223496, -515830359, -1306288356, -1486461488, -99886070, 261913429, -454370658, -1538109120, -586342290, -568419968, 1770475779, 1668129151, 989925924, 1973684065, -1848736516, -1440987069, -751151717, -78533081, -1509851560, 1422530437, 1917703890, -1162759543, -1130350864, -682687162, 1536610005, -1709878924, 1272768630, -989755543, 1873897110, -1520560807, 1827479659, 813023040, -395377963, -1167031859, 1391703481, -242084766, 621915341, -996920608, 1819863051, -1770889433, -1824770114, 831955134, -1433390281, 1036321299, 1223900335, -602717596, -126305173, -888153050, 1364514421, -455286320, 1762167092, 1223729384, 1572152877, -282193997, 180752235, -1386082991, 70102328, 22947882, 81423963, 1058261682, -151387974, 550753330, -384243979, 1771755747, 122783240, 1911552868, 1112162468, 838831151, 803954639, 858486327, -1305326964, -1776128552, 1272194103, 2133269020, 830839496, 854447607, 1533551194, -992286106, 1660145984, 390728933, -520133715, 1367190888, -778875547, 998894949, -886280491, -237809779, -2086926071, 1512054436, -2084071424, -567909622, 1898094925, -1511285251, -1018587433, 1776460938, 1719978075, 634478325, -1938052175, -858312878, -321733511, 1568388703, -592016202, -930193596, -265876753, -1579932985, -1982036270, 317398316, 1381010055, -946369541, 69511070, -4031221, -1779183908, -804769727, -544317637, -277057363, -932201673, -2099697608, -1157596551, -1581843485, 1523195708, -1779180711, -151838493, -1366326648, 1735402444
        }
        ;
        private static readonly HashSet<string> _doubleMountsList = new HashSet<string>() {
            "saddlerear", "saddletest", "bikedriverseat", "bikepassengerseat"
        }
        ;
        private static readonly HashSet<string> _mountsList = new HashSet<string>() {
            "motorbikedriverseat", "motorbikepassengerseat", "modularcardriverseat", "modularcarpassengerseatleft", "modularcarpassengerseatright", "modularcarpassengerseatlesslegroomleft", "modularcarpassengerseatlesslegroomright", "modularcarpassengerseatsidewayleft", "miniheliseat", "minihelipassenger", "transporthelipilot", "transporthelicopilot", "attackhelidriver", "attackheligunner", "submarinesolodriverstanding", "submarineduodriverseat", "submarineduopassengerseat", "snowmobiledriverseat", "snowmobilepassengerseat", "snowmobilepassengerseat tomaha", "workcartdriver", "locomotivedriver", "craneoperator"
        }
        ;
        private static readonly string[] _layersList = new string[] {
            "Under", "Overall", "Overlay", "Hud", "Hud.Menu"
        }
        ;
        private static readonly string[] _fontsList = new string[] {
            "RobotoCondensed-Bold.ttf", "RobotoCondensed-Regular.ttf", "PermanentMarker.ttf", "DroidSansMono.ttf"
        }
        ;
#endregion
#region ~Configuration~
        private static Configuration _config;
        private class Configuration {
            [JsonProperty(PropertyName = "Chat command")]
            public string Command = "bar";
            [JsonProperty(PropertyName = "Is it worth enabling console notifications for the successful loading of local images?")]
            public bool Notify_Images = false;
            [JsonProperty(PropertyName = "Interval(in seconds) for counting in-game status bars")]
            public float Count_Interval = 0.5f;
            [JsonProperty(PropertyName = "Interval(in seconds) for counting Building Privilege status bars.Note: Calculating Building Privilege is significantly more resource-intensive than other counts")]
            public float Count_Interval_Privilege = 1f;
            [JsonProperty(PropertyName = "Bar - Display Layer.If you have button bars, it's advisable to use Hud(https://umod.org/guides/rust/basic-concepts-of-gui#layers)")]
            public string Bar_Layer = "Under";
            [JsonProperty(PropertyName = "Bar - Left to Right")]
            public bool Bar_LeftToRight = true;
            [JsonProperty(PropertyName = "Bar - Offset between status bars")]
            public int Bar_Offset_Between = 2;
            [JsonProperty(PropertyName = "Bar - Default Height")]
            public int Bar_Height = 26;
            [JsonProperty(PropertyName = "Main - Default Color")]
            public string Bar_Main_Color = "#505F75";
            [JsonProperty(PropertyName = "Main - Default Transparency")]
            public float Bar_Main_Transparency = 0.7f;
            [JsonProperty(PropertyName = "Main - Default Material(empty to disable)")]
            public string Bar_Main_Material = "";
            [JsonProperty(PropertyName = "Image - Default Image")]
            public string Bar_Image = "AdvancedBar_Image";
            [JsonProperty(PropertyName = "Image - Default Color")]
            public string Bar_Image_Color = "#6B7E95";
            [JsonProperty(PropertyName = "Image - Default Transparency")]
            public float Bar_Image_Transparency = 1.0f;
            [JsonProperty(PropertyName = "Image - Outline Default Color")]
            public string Bar_Image_Outline_Color = "#000000";
            [JsonProperty(PropertyName = "Image - Outline Default Transparency")]
            public float Bar_Image_Outline_Transparency = 1.0f;
            [JsonProperty(PropertyName = "Image - Outline Default Distance")]
            public string Bar_Image_Outline_Distance = "0.75 0.75";
            [JsonProperty(PropertyName = "Text - Default Size")]
            public int Bar_Text_Size = 12;
            [JsonProperty(PropertyName = "Text - Default Color")]
            public string Bar_Text_Color = "#FFFFFF";
            [JsonProperty(PropertyName = "Text - Default Transparency")]
            public float Bar_Text_Transparency = 1f;
            [JsonProperty(PropertyName = "Text - Default Font(https://umod.org/guides/rust/basic-concepts-of-gui#fonts)")]
            public string Bar_Text_Font = "RobotoCondensed-Bold.ttf";
            [JsonProperty(PropertyName = "Text - Default Offset Horizontal")]
            public int Bar_Text_Offset_Horizontal = 0;
            [JsonProperty(PropertyName = "Text - Outline Default Color")]
            public string Bar_Text_Outline_Color = "#000000";
            [JsonProperty(PropertyName = "Text - Outline Default Transparency")]
            public float Bar_Text_Outline_Transparency = 1.0f;
            [JsonProperty(PropertyName = "Text - Outline Default Distance")]
            public string Bar_Text_Outline_Distance = "0.75 0.75";
            [JsonProperty(PropertyName = "SubText - Default Size")]
            public int Bar_SubText_Size = 12;
            [JsonProperty(PropertyName = "SubText - Default Color")]
            public string Bar_SubText_Color = "#FFFFFF";
            [JsonProperty(PropertyName = "SubText - Default Transparency")]
            public float Bar_SubText_Transparency = 1f;
            [JsonProperty(PropertyName = "SubText - Default Font")]
            public string Bar_SubText_Font = "RobotoCondensed-Bold.ttf";
            [JsonProperty(PropertyName = "SubText - Outline Default Color")]
            public string Bar_SubText_Outline_Color = "#000000";
            [JsonProperty(PropertyName = "SubText - Outline Default Transparency")]
            public float Bar_SubText_Outline_Transparency = 1.0f;
            [JsonProperty(PropertyName = "SubText - Outline Default Distance")]
            public string Bar_SubText_Outline_Distance = "0.75 0.75";
            [JsonProperty(PropertyName = "Progress - Default Color")]
            public string Bar_Progress_Color = "#89B840";
            [JsonProperty(PropertyName = "Progress - Default Transparency")]
            public float Bar_Progress_Transparency = 0.7f;
            [JsonProperty(PropertyName = "Progress - Default OffsetMin")]
            public string Bar_Progress_OffsetMin = "25 2.5";
            [JsonProperty(PropertyName = "Progress - Default OffsetMax")]
            public string Bar_Progress_OffsetMax = "-3.5 -3.5";
            public Oxide.Core.VersionNumber Version;
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                _config = Config.ReadObject<Configuration>();
            }
            catch (Exception ex) {
                PrintError($"{ex.Message}\n\n[{Title}] Your configuration file contains an error.");
            }
            if (_config == null || _config.Version == new VersionNumber()) {
                PrintWarning("The configuration file is not found or contains errors.Creating a new one...");
                LoadDefaultConfig();
            }
            else if (_config.Version < Version) {
                PrintWarning($"Your configuration file version({_config.Version}) is outdated.Updating it to {Version}.");
                _config.Version = Version;
                PrintWarning($"The configuration file has been successfully updated to version {_config.Version}!");
            }
            if (!_layersList.Contains(_config.Bar_Layer)) _config.Bar_Layer = _layersList[0];
            if (!IsStringHexColor(_config.Bar_Main_Color)) _config.Bar_Main_Color = "#505F75";
            _config.Bar_Main_Transparency = Mathf.Clamp01(_config.Bar_Main_Transparency);
            if (!IsStringHexColor(_config.Bar_Image_Color)) _config.Bar_Image_Color = "#6B7E95";
            _config.Bar_Image_Transparency = Mathf.Clamp01(_config.Bar_Image_Transparency);
            if (!IsStringHexColor(_config.Bar_Image_Outline_Color)) _config.Bar_Image_Outline_Color = "#000000";
            _config.Bar_Image_Outline_Transparency = Mathf.Clamp01(_config.Bar_Image_Outline_Transparency);
            _config.Bar_Text_Size = Math.Clamp(_config.Bar_Text_Size, 1, 25);
            if (!IsStringHexColor(_config.Bar_Text_Color)) _config.Bar_Text_Color = "#FFFFFF";
            _config.Bar_Text_Transparency = Mathf.Clamp01(_config.Bar_Text_Transparency);
            _config.Bar_Text_Font = GetValidFont(_config.Bar_Text_Font);
            if (!IsStringHexColor(_config.Bar_Text_Outline_Color)) _config.Bar_Text_Outline_Color = "#000000";
            _config.Bar_Text_Outline_Transparency = Mathf.Clamp01(_config.Bar_Text_Outline_Transparency);
            _config.Bar_SubText_Size = Math.Clamp(_config.Bar_SubText_Size, 1, 25);
            if (!IsStringHexColor(_config.Bar_SubText_Color)) _config.Bar_SubText_Color = "#FFFFFF";
            _config.Bar_SubText_Transparency = Mathf.Clamp01(_config.Bar_SubText_Transparency);
            _config.Bar_SubText_Font = GetValidFont(_config.Bar_SubText_Font);
            if (!IsStringHexColor(_config.Bar_SubText_Outline_Color)) _config.Bar_SubText_Outline_Color = "#000000";
            _config.Bar_SubText_Outline_Transparency = Mathf.Clamp01(_config.Bar_SubText_Outline_Transparency);
            if (!IsStringHexColor(_config.Bar_Progress_Color)) _config.Bar_Progress_Color = "#89B840";
            _config.Bar_Progress_Transparency = Mathf.Clamp01(_config.Bar_Progress_Transparency);
            SaveConfig();
        }
        protected override void SaveConfig() => Config.WriteObject(_config);
        protected override void LoadDefaultConfig() => _config = new Configuration() {
            Version = Version
        }
        ;
#endregion
#region ~Language~
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["MsgDays"]
                = "d", ["MsgHours"] = "h", ["MsgMinutes"] = "m", ["MsgSeconds"] = "s"
            }
            , this);
            lang.RegisterMessages(new Dictionary<string, string> {
                ["MsgDays"]
                = "д", ["MsgHours"] = "ч", ["MsgMinutes"] = "м", ["MsgSeconds"] = "с"
            }
            , this, "ru");
        }
#endregion
#region ~Methods~
        private System.Collections.IEnumerator InitPlugin() {
            for (int i = 0; i <= 24; i++) {
                int y = 100 + (28 * i);
                _cachedBarsContainer[i] = $@"[{{""name"":""{AdvancedStatusName}"",""parent"":""{_config.Bar_Layer}"",""components"":[{{""type"":""UnityEngine.UI.Image"",""color"":""0 0 0 0""}},
{{""type"":""RectTransform"",""anchormin"":""1 0"",""anchormax"":""1 0"",""offsetmin"":""-208 {y}"",""offsetmax"":""-16 {y + 1500}""}}]}}]";
            }
            yield return ServerMgr.Instance.StartCoroutine(InitImages());
            yield return new WaitForSeconds(1);
            foreach (var player in BasePlayer.activePlayerList) {
                if (!player.IsNpc) InitPlayer(player);
            }
            Subscribe(nameof(OnPlayerConnected));
            Subscribe(nameof(OnPlayerDisconnected));
            Subscribe(nameof(OnPlayerSleep));
            Subscribe(nameof(OnPlayerSleepEnded));
            Subscribe(nameof(OnEntityDeath));
            Subscribe(nameof(OnSendCommand));
            Subscribe(nameof(OnEntityMounted));
            Subscribe(nameof(OnEntityDismounted));
            Subscribe(nameof(OnNpcConversationStart));
            Subscribe(nameof(OnNpcConversationEnded));
            _isReady = true;
            yield return new WaitForSeconds(1);
            Interface.CallHook(Hooks_OnLoaded, Version);
        }
        private System.Collections.IEnumerator InitImages() {
            string[] images = Interface.Oxide.DataFileSystem.GetFiles(ImagesPath, ImagesPattern);
            if (images.Any()) {
                int lastBackslash, lastDot;
                string name;
                foreach (var path in images) {
                    if (string.IsNullOrWhiteSpace(path)) continue;
                    lastBackslash = path.LastIndexOf('\\');
                    lastDot = path.LastIndexOf('.');
                    name = path.Substring(lastBackslash + 1, lastDot - lastBackslash - 1);
                    yield return ServerMgr.Instance.StartCoroutine(StoreImage(name, path));
                }
            }
            else PrintWarning($"The image folder is empty! Path: {Interface.Oxide.DataFileSystem.Directory}\\{ImagesPath}");
        }
        private System.Collections.IEnumerator StoreImages(Dictionary<string, string> images) {
            foreach (var kvp in images) yield return ServerMgr.Instance.StartCoroutine(StoreImage(kvp.Key, kvp.Value));
        }
        private System.Collections.IEnumerator StoreImage(string name, string path) {
            using (UnityWebRequest request = UnityWebRequestTexture.GetTexture($"file://{path}")) {
                yield return request.SendWebRequest();
                if (request.result != UnityWebRequest.Result.Success) {
                    PrintError($"Failed to load the image {name} from {path}");
                    yield break;
                }
                Texture2D tex = DownloadHandlerTexture.GetContent(request);
                if (_imagesList.ContainsKey(name)) FileStorage.server.Remove(uint.Parse(_imagesList[name]), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID);
                _imagesList[name] = FileStorage.server.Store(tex.EncodeToPNG(), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
                if (_config.Notify_Images) Puts($"{name} has been stored successfully");
                UnityEngine.Object.DestroyImmediate(tex);
            }
        }
        private void InitPlayer(BasePlayer player) {
            RemovePlayer(player);
            _playersList[player.userID] = player.gameObject.AddComponent<PlayerWatcher>();
        }
        private void RemovePlayer(BasePlayer player) {
            var playerWatcher = player.gameObject.GetComponent<PlayerWatcher>();
            if (playerWatcher != null) UnityEngine.Object.DestroyImmediate(playerWatcher);
            _playersList.Remove(player.userID);
        }
        private bool IsRightItem(ItemDefinition itemDef) {
            if (itemDef != null && !_excludedBuildingItemCategories.Contains(itemDef.category)) {
                if (_buildingBlockItemCategories.Contains(itemDef.category)) return true;
                if (_buildingBlockItemCategories2.Contains(itemDef.category)) {
                    if (_buildingBlockItems.Contains(itemDef.itemid)) return true;
                }
                else if (!_exceptionBuildingItems.Contains(itemDef.itemid)) return true;
            }
            return false;
        }
        public static BuildingPrivlidge GetBuildingPrivilege(BasePlayer player) {
            var obb = new OBB(player.transform.position, player.transform.lossyScale, player.transform.rotation, player.bounds);
            BuildingBlock other = null;
            BuildingPrivlidge result = null;
            var obj2 = Pool.Get<List<BuildingBlock>>();
            Vis.Entities(obb.position, 16f + obb.extents.magnitude, obj2, 2097152);
            for (int i = 0; i < obj2.Count; i++) {
                var buildingBlock = obj2[i];
                if (buildingBlock.isServer != player.isServer || !buildingBlock.IsOlderThan(other) || obb.Distance(buildingBlock.WorldSpaceBounds()) > 16f) continue;
                var building = buildingBlock.GetBuilding();
                if (building != null) {
                    var dominatingBuildingPrivilege = building.GetDominatingBuildingPrivilege();
                    if (!(dominatingBuildingPrivilege == null)) {
                        other = buildingBlock;
                        result = dominatingBuildingPrivilege;
                    }
                }
            }
            Pool.FreeUnmanaged(ref obj2);
            return result;
        }
        public static bool TryGetEntityPrivilege(BasePlayer player, out EntityPrivilege result) {
            var obb = new OBB(player.transform.position, player.transform.lossyScale, player.transform.rotation, player.bounds);
            LegacyShelter other = null;
            var obj = Pool.Get<List<LegacyShelter>>();
            Vis.Entities(obb.position, 10f, obj, 2097152);
            for (int i = 0; i < obj.Count; i++) {
                var shelter = obj[i];
                if (shelter.isServer != player.isServer || !shelter.IsOlderThan(other) || obb.Distance(shelter.WorldSpaceBounds()) > 3f) continue;
                other = shelter;
            }
            Pool.FreeUnmanaged(ref obj);
            result = other?.GetEntityBuildingPrivilege();
            return result != null;
        }
        public static List<VehiclePrivilege> GetVehiclePrivileges(BasePlayer player) {
            var obb = new OBB(player.transform.position, player.transform.lossyScale, player.transform.rotation, player.bounds);
            var result = new List<VehiclePrivilege>();
            var pos = Pool.Get<List<Vector3>>();
            var obj = Pool.Get<List<Tugboat>>();
            Vis.Entities(obb.position, 1f, obj);
            for (int i = 0; i < obj.Count; i++) {
                var tug = obj[i];
                if (tug.isServer != player.isServer || tug.children == null || obb.Distance(tug.WorldSpaceBounds()) > 3f || pos.Contains(tug.transform.position)) continue;
                pos.Add(tug.transform.position);
                foreach (var child in tug.children) {
                    if (child is VehiclePrivilege) result.Add((VehiclePrivilege)child);
                }
            }
            Pool.FreeUnmanaged(ref pos);
            Pool.FreeUnmanaged(ref obj);
            return result;
        }
        public static void SortAdvancedBars(List<AdvancedBar> bars) {
            bars.Sort((b1, b2) => {
                int orderComparison = b1.Order.CompareTo(b2.Order);
                return (orderComparison != 0) ? orderComparison : b1.Id.CompareTo(b2.Id);
            }
            );
        }
        public static bool IsStringHexColor(string hexColor) => !string.IsNullOrWhiteSpace(hexColor) && hexColor[0] == '#' && hexColor.Length == 7;
        public static string StringColorFromHex(string hexColor, float transparent) {
            if (string.IsNullOrWhiteSpace(hexColor)) return $"1 1 1 {transparent:F2}";
            if (hexColor[0] != '#' || hexColor.Length < 7) return hexColor;
            int red = Convert.ToInt32(hexColor.Substring(1, 2), 16);
            int green = Convert.ToInt32(hexColor.Substring(3, 2), 16);
            int blue = Convert.ToInt32(hexColor.Substring(5, 2), 16);
            double redPercentage = (double)red / 255;
            double greenPercentage = (double)green / 255;
            double bluePercentage = (double)blue / 255;
            return $"{redPercentage:F2} {greenPercentage:F2} {bluePercentage:F2} {transparent:F2}";
        }
        public static string GetValidFont(string font) {
            for (int i = 0; i < _fontsList.Length; i++) {
                if (string.Equals(_fontsList[i], font, StringComparison.OrdinalIgnoreCase)) return _fontsList[i];
            }
            return _fontsList[0];
        }
#endregion
#region ~API~
        private object IsReady() => _isReady ? true : null;
        private void CreateBar(object obj, Dictionary<string, object> parameters) => CreateBar($"{obj}", parameters);
        private void CreateBar(string userIDStr, Dictionary<string, object> parameters) {
            if (ulong.TryParse(userIDStr, out var userID)) CreateBar(userID, parameters);
        }
        private void CreateBar(BasePlayer player, Dictionary<string, object> parameters) => CreateBar(player.userID.Get(), parameters);
        private void CreateBar(ulong userID, Dictionary<string, object> parameters) {
            if (parameters == null || !userID.IsSteamId() || !parameters.TryGetValue("Plugin", out var pNameObj) || pNameObj is not string pluginName || !parameters.TryGetValue("Id", out var bIdObj) || bIdObj is not string barId) return;
            if (!_playersList.TryGetValue(userID, out var watcher)) {
                if (BasePlayer.TryFindByID(userID, out var player)) {
                    InitPlayer(player);
                    watcher = _playersList[userID];
                }
                else return;
            }
            AdvancedBar bar = null;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                var tBar = watcher.Bars[i];
                if (tBar.Plugin == pluginName && tBar.Id == barId) {
                    bar = tBar;
                    break;
                }
            }
            bool isOrder = true;
            if (bar != null) bar.Update(parameters, out var isProgress, out var isText, out isOrder);
            else {
                bar = new AdvancedBar(pluginName, barId, parameters);
                watcher.Bars.Add(bar);
            }
            if (isOrder) SortAdvancedBars(watcher.Bars);
            bar.ShouldRemove = false;
            if (watcher.CanShowBars) DrawBars(watcher, !watcher.IsUiActive ? 0 : watcher.Bars.IndexOf(bar));
        }
        private void UpdateContent(object obj, Dictionary<string, object> parameters) => UpdateContent($"{obj}", parameters);
        private void UpdateContent(string userIDStr, Dictionary<string, object> parameters) {
            if (ulong.TryParse(userIDStr, out var userID)) UpdateContent(userID, parameters);
        }
        private void UpdateContent(BasePlayer player, Dictionary<string, object> parameters) => UpdateContent(player.userID.Get(), parameters);
        private void UpdateContent(ulong userID, Dictionary<string, object> parameters) {
            if (parameters == null || !parameters.TryGetValue("Plugin", out var pNameObj) || pNameObj is not string pluginName || !parameters.TryGetValue("Id", out var bIdObj) || bIdObj is not string barId || !_playersList.TryGetValue(userID, out var watcher)) return;
            AdvancedBar bar;
            bool isOrder = false;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                bar = watcher.Bars[i];
                if (bar.Plugin == pluginName && bar.Id == barId) {
                    bar.Update(parameters, out var isProgress, out var isText, out isOrder);
                    if (watcher.IsUiActive) {
                        if (isProgress) DrawProgress(watcher.Player, bar);
                        if (isText) DrawText(watcher.Player, bar);
                    }
                    break;
                }
            }
            if (isOrder) SortAdvancedBars(watcher.Bars);
        }
        private void CreateBar(object obj, Dictionary<int, object> parameters) => CreateBar($"{obj}", parameters);
        private void CreateBar(string userIDStr, Dictionary<int, object> parameters) {
            if (ulong.TryParse(userIDStr, out var userID)) CreateBar(userID, parameters);
        }
        private void CreateBar(BasePlayer player, Dictionary<int, object> parameters) => CreateBar(player.userID.Get(), parameters);
        private void CreateBar(ulong userID, Dictionary<int, object> parameters) {
            if (parameters == null || !userID.IsSteamId() || !parameters.TryGetValue(1, out var pNameObj) || pNameObj is not string pluginName || !parameters.TryGetValue(0, out var bIdObj) || bIdObj is not string barId) return;
            if (!_playersList.TryGetValue(userID, out var watcher)) {
                if (BasePlayer.TryFindByID(userID, out var player)) {
                    InitPlayer(player);
                    watcher = _playersList[userID];
                }
                else return;
            }
            AdvancedBar bar = null;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                var tBar = watcher.Bars[i];
                if (tBar.Plugin == pluginName && tBar.Id == barId) {
                    bar = tBar;
                    break;
                }
            }
            bool isOrder = true;
            if (bar != null) bar.Update(parameters, out var isProgress, out var isText, out isOrder);
            else {
                bar = new AdvancedBar(pluginName, barId, parameters);
                watcher.Bars.Add(bar);
            }
            if (isOrder) SortAdvancedBars(watcher.Bars);
            bar.ShouldRemove = false;
            if (watcher.CanShowBars) DrawBars(watcher, !watcher.IsUiActive ? 0 : watcher.Bars.IndexOf(bar));
        }
        private void UpdateContent(object obj, Dictionary<int, object> parameters) => UpdateContent($"{obj}", parameters);
        private void UpdateContent(string userIDStr, Dictionary<int, object> parameters) {
            if (ulong.TryParse(userIDStr, out var userID)) UpdateContent(userID, parameters);
        }
        private void UpdateContent(BasePlayer player, Dictionary<int, object> parameters) => UpdateContent(player.userID.Get(), parameters);
        private void UpdateContent(ulong userID, Dictionary<int, object> parameters) {
            if (parameters == null || !parameters.TryGetValue(1, out var pNameObj) || pNameObj is not string pluginName || !parameters.TryGetValue(0, out var bIdObj) || bIdObj is not string barId || !_playersList.TryGetValue(userID, out var watcher)) return;
            AdvancedBar bar;
            bool isOrder = false;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                bar = watcher.Bars[i];
                if (bar.Plugin == pluginName && bar.Id == barId) {
                    bar.Update(parameters, out var isProgress, out var isText, out isOrder);
                    if (watcher.IsUiActive) {
                        if (isProgress) DrawProgress(watcher.Player, bar);
                        if (isText) DrawText(watcher.Player, bar);
                    }
                    break;
                }
            }
            if (isOrder) SortAdvancedBars(watcher.Bars);
        }
        private void DeleteBar(object obj, string barId, string pluginName) => DeleteBar($"{obj}", barId, pluginName);
        private void DeleteBar(string userIDStr, string barId, string pluginName) {
            if (ulong.TryParse(userIDStr, out var userID)) DeleteBar(userID, barId, pluginName);
        }
        private void DeleteBar(BasePlayer player, string barId, string pluginName) => DeleteBar(player.userID.Get(), barId, pluginName);
        private void DeleteBar(ulong userID, string barId, string pluginName) {
            if (!_playersList.TryGetValue(userID, out var watcher)) return;
            AdvancedBar bar;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                bar = watcher.Bars[i];
                if (bar.Plugin == pluginName && bar.Id == barId) {
                    bar.ShouldRemove = true;
                    break;
                }
            }
        }
        private void DeleteBarForAll(string barId, string pluginName) {
            AdvancedBar bar;
            foreach (var watcher in _playersList.Values) {
                for (int i = 0; i < watcher.Bars.Count; i++) {
                    bar = watcher.Bars[i];
                    if (bar.Plugin == pluginName && bar.Id == barId) {
                        bar.ShouldRemove = true;
                        break;
                    }
                }
            }
        }
        private void DeleteCategory(object obj, string category, string pluginName) => DeleteCategory($"{obj}", category, pluginName);
        private void DeleteCategory(string userIDStr, string category, string pluginName) {
            if (ulong.TryParse(userIDStr, out var userID)) DeleteCategory(userID, category, pluginName);
        }
        private void DeleteCategory(BasePlayer player, string category, string pluginName) => DeleteCategory(player.userID.Get(), category, pluginName);
        private void DeleteCategory(ulong userID, string category, string pluginName) {
            if (!_playersList.TryGetValue(userID, out var watcher)) return;
            AdvancedBar bar;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                bar = watcher.Bars[i];
                if (bar.Plugin == pluginName && bar.Category == category) bar.ShouldRemove = true;
            }
        }
        private void DeleteCategoryForAll(string category, string pluginName) {
            AdvancedBar bar;
            foreach (var watcher in _playersList.Values) {
                for (int i = 0; i < watcher.Bars.Count; i++) {
                    bar = watcher.Bars[i];
                    if (bar.Plugin == pluginName && bar.Category == category) bar.ShouldRemove = true;
                }
            }
        }
        private void DeleteAllBars(object obj, string pluginName) => DeleteAllBars($"{obj}", pluginName);
        private void DeleteAllBars(string userIDStr, string pluginName) {
            if (ulong.TryParse(userIDStr, out var userID)) DeleteAllBars(userID, pluginName);
        }
        private void DeleteAllBars(BasePlayer player, string pluginName) => DeleteAllBars(player.userID.Get(), pluginName);
        private void DeleteAllBars(ulong userID, string pluginName) {
            if (!_playersList.TryGetValue(userID, out var watcher)) return;
            AdvancedBar bar;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                bar = watcher.Bars[i];
                if (bar.Plugin == pluginName) bar.ShouldRemove = true;
            }
        }
        private void DeleteAllPluginBars(string pluginName) {
            AdvancedBar bar;
            foreach (var watcher in _playersList.Values) {
                for (int i = 0; i < watcher.Bars.Count; i++) {
                    bar = watcher.Bars[i];
                    if (bar.Plugin == pluginName) bar.ShouldRemove = true;
                }
            }
        }
        private int GetTotalClientBars(object obj) => GetTotalClientBars($"{obj}");
        private int GetTotalClientBars(string userIDStr) => ulong.TryParse(userIDStr, out var userID) ? GetTotalClientBars(userID) : 0;
        private int GetTotalClientBars(BasePlayer player) => GetTotalClientBars(player.userID.Get());
        private int GetTotalClientBars(ulong userID) => _playersList.TryGetValue(userID, out var watcher) ? Math.Max(watcher.ClientBars, 0) : 0;
        private int GetTotalPlayerBars(object obj) => GetTotalPlayerBars($"{obj}");
        private int GetTotalPlayerBars(string userIDStr) => ulong.TryParse(userIDStr, out var userID) ? GetTotalPlayerBars(userID) : 0;
        private int GetTotalPlayerBars(BasePlayer player) => GetTotalPlayerBars(player.userID.Get());
        private int GetTotalPlayerBars(ulong userID) {
            int result = 0;
            if (_playersList.TryGetValue(userID, out var watcher)) {
                for (int i = 0; i < watcher.Bars.Count; i++) {
                    if (!watcher.Bars[i].ShouldRemove) result++;
                }
            }
            return result;
        }
        private void LoadImages(List<string> list, bool force = false) {
            Dictionary<string, string> images;
            if (force) images = list.Where(i => !string.IsNullOrWhiteSpace(i)).ToDictionary(i => i, i => string.Format(ImagePath, i));
            else {
                string path;
                images = new Dictionary<string, string>();
                for (int i = 0; i < list.Count; i++) {
                    var name = list[i];
                    if (!string.IsNullOrWhiteSpace(name) && !_imagesList.ContainsKey(name)) {
                        path = string.Format(ImagePath, name);
                        if (!_imagesList.ContainsKey(name) && File.Exists(path)) images[name] = string.Format(ImagePath, name);
                    }
                }
            }
            ServerMgr.Instance.StartCoroutine(StoreImages(images));
        }
        private void LoadImage(string name, bool force = false) {
            if (string.IsNullOrWhiteSpace(name) || (!force && _imagesList.ContainsKey(name))) return;
            string path = string.Format(ImagePath, name);
            if (File.Exists(path)) ServerMgr.Instance.StartCoroutine(StoreImage(name, path));
        }
        private void CopyImage(string source, string newImage, bool force = false) {
            if (string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(newImage)) return;
            string sourcePath = string.Format(ImagePath, source), newPath = string.Format(ImagePath, newImage);
            if (File.Exists(sourcePath) && (force || !File.Exists(newPath))) {
                try {
                    File.Copy(sourcePath, newPath, overwrite : true);
                    ServerMgr.Instance.StartCoroutine(StoreImage(newImage, newPath));
                }
                catch {
                }
            }
        }
        private void DeleteImages(List<string> list, bool deleteFile = true) {
            for (int i = 0; i < list.Count; i++) DeleteImage(list[i], deleteFile);
        }
        private void DeleteImage(string name, bool deleteFile = true) {
            if (string.IsNullOrWhiteSpace(name)) return;
            if (_imagesList.TryGetValue(name, out var crcStr)) {
                uint crc = uint.Parse(crcStr);
                FileStorage.server.Remove(crc, FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID);
                _imagesList.Remove(name);
            }
            if (deleteFile) {
                try {
                    File.Delete(string.Format(ImagePath, name));
                }
                catch {
                }
            }
        }
        private bool BarExists(object obj, string barId, string pluginName) => BarExists($"{obj}", barId, pluginName);
        private bool BarExists(string userIDStr, string barId, string pluginName) => ulong.TryParse(userIDStr, out var userID) ? BarExists(userID, barId, pluginName) : false;
        private bool BarExists(BasePlayer player, string barId, string pluginName) => BarExists(player.userID.Get(), barId, pluginName);
        private bool BarExists(ulong userID, string barId, string pluginName) {
            if (_playersList.TryGetValue(userID, out var watcher)) {
                AdvancedBar bar;
                for (int i = 0; i < watcher.Bars.Count; i++) {
                    bar = watcher.Bars[i];
                    if (bar.Plugin == pluginName && bar.Id == barId) return true;
                }
            }
            return false;
        }
        private bool InBuildingPrivilege(object obj) => InBuildingPrivilege($"{obj}");
        private bool InBuildingPrivilege(string userIDStr) => ulong.TryParse(userIDStr, out var userID) ? InBuildingPrivilege(userID) : false;
        private bool InBuildingPrivilege(BasePlayer player) => InBuildingPrivilege(player.userID.Get());
        private bool InBuildingPrivilege(ulong userID) => _playersList.TryGetValue(userID, out var watcher) ? watcher.InOwnBuilding : false;
#endregion
#region ~Oxide Hooks~
        void OnPlayerConnected(BasePlayer player) {
            if (!_playersList.ContainsKey(player.userID)) InitPlayer(player);
        }
        void OnPlayerDisconnected(BasePlayer player, string reason) => RemovePlayer(player);
        void OnPlayerSleep(BasePlayer player) {
            if (_playersList.TryGetValue(player.userID, out var watcher)) watcher.OnDeathOrSleeping();
        }
        void OnPlayerSleepEnded(BasePlayer player) {
            if (_playersList.TryGetValue(player.userID, out var watcher)) {
                watcher.IsDeadOrSleeping = false;
                watcher.StartCount();
            }
        }
        void OnEntityDeath(BasePlayer player, HitInfo info) {
            if (_playersList.TryGetValue(player.userID, out var watcher)) watcher.OnDeathOrSleeping(false);
        }
        void OnSendCommand(Connection connection, string command, object[] args) {
            if (connection == null || !command.StartsWith(NoteInv) || !_playersList.TryGetValue(connection.userid, out var watcher)) return;
            int itemId = 0;
            if (!(command == NoteInv && int.TryParse(args[0].ToString(), out itemId))) {
                string[] parts = command.Split(" ");
                if (parts.Length > 1 && int.TryParse(parts[1], out itemId)) {
                }
            }
            var realtimeSinceStartup = Time.realtimeSinceStartup;
            if (!_stackableItems.Contains(itemId)) watcher.AddedItems[$"{itemId}_{realtimeSinceStartup}"] = realtimeSinceStartup + 3.7f;
            else watcher.AddedItems[itemId.ToString()] = realtimeSinceStartup + 3.7f;
        }
        void OnEntityMounted(BaseMountable mount, BasePlayer player) {
            if (_playersList.TryGetValue(player.userID, out var watcher)) watcher.OnMount(mount);
        }
        void OnEntityDismounted(BaseMountable mount, BasePlayer player) {
            if (!player.isMounted && _playersList.TryGetValue(player.userID, out var watcher)) watcher.MountCount = 0;
        }
        void OnNpcConversationStart(NPCTalking npcTalking, BasePlayer player, ConversationData conversationData) {
            NextTick(() => {
                //npcTalking.conversingPlayers.Contains(player) - Not the best solution, as the conversation UI will display the status bar UI.if (npcTalking.conversingPlayers.Contains(player) && _playersList.TryGetValue(player.userID, out var watcher))
                watcher.OnConversing();
            }
            );
        }
        void OnNpcConversationEnded(NPCTalking npcTalking, BasePlayer player) {
            if (_playersList.TryGetValue(player.userID, out var watcher) && watcher.IsConversing) {
                watcher.IsConversing = false;
                if (watcher.CanShowBars) watcher.StartCount();
            }
        }
        void OnPluginUnloaded(Plugin plugin) => DeleteAllPluginBars(plugin.Name);
        void Init() {
            Instance = this;
            Unsubscribe(nameof(OnPlayerConnected));
            Unsubscribe(nameof(OnPlayerDisconnected));
            Unsubscribe(nameof(OnPlayerSleep));
            Unsubscribe(nameof(OnPlayerSleepEnded));
            Unsubscribe(nameof(OnEntityDeath));
            Unsubscribe(nameof(OnSendCommand));
            Unsubscribe(nameof(OnEntityMounted));
            Unsubscribe(nameof(OnEntityDismounted));
            Unsubscribe(nameof(OnNpcConversationStart));
            Unsubscribe(nameof(OnNpcConversationEnded));
            permission.RegisterPermission(PERMISSION_ADMIN, this);
            AddCovalenceCommand(_config.Command, nameof(AdvancedStatus_Command));
        }
        void OnServerInitialized(bool initial) {
            if (initial) {
                Interface.Oxide.ReloadPlugin(Name);
                return;
            }
            string folderPath = $"{Interface.Oxide.DataDirectory}{Path.DirectorySeparatorChar}{AdvancedStatusName}{Path.DirectorySeparatorChar}Images";
            ImagePath = $"{folderPath}{Path.DirectorySeparatorChar}{{0}}.png";
            if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
            ServerMgr.Instance.StartCoroutine(InitPlugin());
        }
#endregion
#region ~Commands~
        private void AdvancedStatus_Command(IPlayer player, string command, string[] args) {
            if (args == null || args.Length < 3 || (!player.IsServer && !permission.UserHasPermission(player.Id, PERMISSION_ADMIN))) return;
            if (args[0] == "images") {
                if (args[1] == "reload") {
                    if (args[2] == "all") ServerMgr.Instance.StartCoroutine(InitImages());
                    else LoadImage(args[2], true);
                }
            }
        }
#endregion
#region ~UI~
        private void DrawBars(PlayerWatcher watcher, int start = 0) {
            if (start <= 0) {
                start = Math.Max(start, 0);
                CuiHelper.DestroyUi(watcher.Player, AdvancedStatusName);
                CuiHelper.AddUi(watcher.Player, _cachedBarsContainer[Math.Clamp(watcher.ClientBars, 0, 24)]);
                watcher.IsUiActive = true;
            }
            int barOffset = 0;
            for (int i = 0; i < watcher.Bars.Count; i++) {
                var ba
// ... [Code preview truncated due to length. Full source in attached file] ...

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