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

FREE Shop : 2.4.15 2.4.15

Нет прав для скачивания
C#:
// #define TESTING
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.ShopExtensionMethods;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Debug = UnityEngine.Debug;
using Global = Rust.Global;
using Random = UnityEngine.Random;
using Time = UnityEngine.Time;
#if CARBON
using Carbon.Base;
using Carbon.Modules;
#endif
namespace Oxide.Plugins {
    [Info("Shop", "Mevent", "2.4.15")]
    public class Shop : RustPlugin {
#region Fields
        [PluginReference]
        private Plugin ImageLibrary = null, ServerPanel = null, ItemCostCalculator = null, LangAPI = null, Notify = null, UINotify = null, NoEscape = null, Duel = null, Duelist = null;
        private static Shop Instance;
        private (bool spStatus, int categoryID) _serverPanelCategory = (false, -1);
        // key - use serverPanel, value - category id
#if CARBON
        private ImageDatabaseModule imageDatabase;
#endif
        private const bool LangRu = false;
        private readonly Dictionary<int, ShopItem> _shopItems = new();
        private readonly Dictionary<ulong, Coroutine> _coroutines = new();
        private readonly Dictionary<ulong, float> _lastCommandTime = new();
        private readonly Dictionary<string, List<(int itemID, string shortName)>> _itemsCategories = new();
        private readonly HashSet<string> _images = new();
        private const string Layer = "UI.Shop", ModalLayer = "UI.Shop.Modal", EditingLayer = "UI.Shop.Editing", CmdMainConsole = "UI_Shop";
        private const string PERM_ADMIN = "shop.admin", PERM_FREE_BYPASS = "shop.free", PERM_SET_VM = "shop.setvm", PERM_SET_NPC = "shop.setnpc", PERM_BYPASS_DLC = "shop.bypass.dlc";
        private const int _itemsPerTick = 10;
        private readonly Dictionary<ulong, NPCShop> _openedShopsNPC = new();
        private readonly HashSet<ulong> _adminModeUsers = new();
        private bool _isEnabledFavorites;
        private (bool status, string message) _initializedStatus = (false, string.Empty);
        private bool _templateMigrationInProgress;
#endregion
#region Config
        private static Configuration _config;
        private class Configuration {
#region Fields
            [JsonProperty(PropertyName = LangRu ? "Разрешение для использования плагина (прим: shop.use)" : "Permission to use plugin (ex: shop.use)")]
            public string Permission = string.Empty;
            [JsonProperty(PropertyName = LangRu ? "Команды" : "Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public string[] Commands = {
                "shop", "shops"
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Включить переводы денег между игроками?" : "Enable money transfers between players?")]
            public bool Transfer = true;
            [JsonProperty(PropertyName = LangRu ? "Разрешить переводы денег оффлайн игрокам?" : "Allow money transfers to offline players?")]
            public bool TransferToOfflinePlayers = false;
            [JsonProperty(PropertyName = LangRu ? "Включить продажу предметов?" : "Enable selling items?")]
            public bool EnableSelling = true;
            [JsonProperty(PropertyName = LangRu ? "Включить логирование в консоль?" : "Enable logging to the console?")]
            public bool LogToConsole = true;
            [JsonProperty(PropertyName = LangRu ? "Включить логирование в файл?" : "Enable logging to the file?")]
            public bool LogToFile = true;
            [JsonProperty(PropertyName = LangRu ? "Загружать изображения при подключении к серверу?" : "Load images when logging into the server?")]
            public bool LoginImages = true;
            [JsonProperty(PropertyName = LangRu ? "Работать с Notify?" : "Work with Notify?")]
            public bool UseNotify = true;
            [JsonProperty(PropertyName = LangRu ? "Включить режим оффлайн изображений" : "Enable Offline Image Mode")]
            public bool EnableOfflineImageMode = false;
            [JsonProperty(PropertyName = LangRu ? "Включить работу с LangAPI?" : "Work with LangAPI?")]
            public bool UseLangAPI = true;
            [JsonProperty(PropertyName = LangRu ? "Могут ли админы редактировать предметы? (флаг)" : "Can admins edit? (by flag)")]
            public bool FlagAdmin = false;
            [JsonProperty(PropertyName = LangRu ? "Поддержка NoEscape" : "Block (NoEscape)")]
            public bool BlockNoEscape = false;
            [JsonProperty(PropertyName = LangRu ? "Включить блокировку после вайпа" : "Wipe Block")]
            public bool WipeCooldown = false;
            [JsonProperty(PropertyName = LangRu ? "Длительность блокировки после вайпа" : "Wipe Cooldown")]
            public float WipeCooldownTimer = 3600;
            [JsonProperty(PropertyName = LangRu ? "Включить блокировку после респавна" : "Respawn Block")]
            public bool RespawnCooldown = true;
            [JsonProperty(PropertyName = LangRu ? "Длительность блокировки после респавна" : "Respawn Cooldown")]
            public float RespawnCooldownTimer = 60;
            [JsonProperty(PropertyName = LangRu ? "Запрещать открытие на дуэлях?" : "Blocking the opening in duels?")]
            public bool UseDuels = false;
            [JsonProperty(PropertyName = LangRu ? "Задержка между действиями (в секундах)" : "Cooldown between actions (in seconds)")]
            public float CooldownBetweenActions = 0.1f;
            [JsonProperty(PropertyName = LangRu ? "Задержка между загрузкой изображений" : "Delay between loading images")]
            public float ImagesDelay = 1f;
            [JsonProperty(PropertyName = LangRu ? "Экономика" : "Economy")]
            public EconomyEntry Economy = new() {
                Type = EconomyType.Plugin, AddHook = "Deposit", BalanceHook = "Balance", RemoveHook = "Withdraw", Plug = "Economics", ShortName = "scrap", DisplayName = string.Empty, Skin = 0, EconomyTitle = new EconomyTitle("Economics"), EconomyBalance = new EconomyTitle("${0}"), EconomyPrice = new EconomyTitle("${0}"), EconomyFooterPrice = new EconomyTitle("${0}")
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Дополнительная экономика" : "Additional Economics", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<AdditionalEconomy> AdditionalEconomics = new() {
                new AdditionalEconomy {
                    ID = 1, Enabled = true, Type = EconomyType.Plugin, AddHook = "AddPoints", BalanceHook = "CheckPoints", RemoveHook = "TakePoints", Plug = "ServerRewards", ShortName = "scrap", DisplayName = string.Empty, Skin = 0, EconomyTitle = new EconomyTitle("Server Rewards"), EconomyBalance = new EconomyTitle("{0} RP"), EconomyPrice = new EconomyTitle("{0} RP"), EconomyFooterPrice = new EconomyTitle("{0} RP")
                }
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Магазины NPC (NPC ID - категории магазина)" : "NPC Shops (NPC ID - shop categories)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, NPCShop> NPCs = new() {
                ["1234567"]
                = new NPCShop {
                    Permission = string.Empty, Categories = new List<string> {
                        "Tool", "Food"
                    }
                }
                , ["7654321"] = new NPCShop {
                    Permission = string.Empty, Categories = new List<string> {
                        "Weapon", "Ammunition"
                    }
                }
                , ["4644687478"] = new NPCShop {
                    Permission = "shop.usenpc", Categories = new List<string> {
                        "*"
                    }
                }
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Интерфейс" : "Interface")]
            public UserInterface UI = new() {
                DisplayType = "OverlayNonScaled", RoundDigits = 5, Color1 = IColor.Create("#161617"), Color2 = IColor.Create("#4B68FF"), Color3 = IColor.Create("#0E0E10"), Color5 = IColor.Create("#FF4B4B"), Color7 = IColor.Create("#CD3838"), Color8 = IColor.Create("#FFFFFF"), Color9 = IColor.Create("#4B68FF", 33), Color10 = IColor.Create("#4B68FF", 50), Color11 = IColor.Create("#161617", 95), Color12 = IColor.Create("#161617", 80), Color13 = IColor.Create("#0E0E10", 98)
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Заблокированные скины для продажи" : "Blocked skins for sell", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, List<ulong>> BlockedSkins = new() {
                ["short name"]
                = new List<ulong> {
                    52, 25
                }
                , ["short name 2"] = new List<ulong> {
                    52, 25
                }
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Auto-Wipe настройки" : "Auto-Wipe Settings")]
            public WipeSettings Wipe = new() {
                Cooldown = true, Players = true, Limits = true
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Кастомные Торговые Автоматы (Entity ID - settings)" : "Custom Vending Machines (Entity ID - settings)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<ulong, CustomVendingEntry> CustomVending = new() {
                [123343941]
                = new CustomVendingEntry {
                    Permission = string.Empty, Categories = new List<string> {
                        "Cars", "Misc"
                    }
                }
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Настройки контейнеров для продажи товаров" : "Settings available containers for selling item")]
            public SellContainers SellContainers = new() {
                Enabled = true, Containers = new List<string> {
                    "main", "belt"
                }
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Настройки повторной покупки" : "Buy Again Settings")]
            public BuyAgainConf BuyAgain = new() {
                Enabled = false, Permission = string.Empty, Image = "assets/icons/history_servers.png"
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Настройки форматирования" : "Formatting Settings")]
            public FormattingConf Formatting = new() {
                BuyPriceFormat = "G", SellPriceFormat = "G", ShoppingBagCostFormat = "G", BalanceFormat = "G"
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Скидка" : "Discount")]
            public DiscountConf Discount = new() {
                Enabled = true, Discount = new Dictionary<string, int> {
                    ["shop.default"]
                    = 0, ["shop.vip"] = 10
                }
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Уведомления" : "Notifications")]
            public NotificationsConf Notifications = new() {
                GeneralNotifications = new Dictionary<string, NotificationsConf.BaseNotification> {
                    [NoPermission]
                    = NotificationsConf.BaseNotification.Create(1), [ErrorSyntax] = NotificationsConf.BaseNotification.Create(1), [VMNotFoundCategories] = NotificationsConf.BaseNotification.Create(1), [VMNotFound] = NotificationsConf.BaseNotification.Create(1), [VMExists] = NotificationsConf.BaseNotification.Create(1), [VMInstalled] = NotificationsConf.BaseNotification.Create(0), [NPCNotFound] = NotificationsConf.BaseNotification.Create(1), [NPCInstalled] = NotificationsConf.BaseNotification.Create(0), [BuyCooldownMessage] = NotificationsConf.BaseNotification.Create(1), [ReceivedItems] = NotificationsConf.BaseNotification.Create(0), [SellNotify] = NotificationsConf.BaseNotification.Create(0), [SuccessfulTransfer] = NotificationsConf.BaseNotification.Create(0), [MsgIsFavoriteItem] = NotificationsConf.BaseNotification.Create(1), [MsgAddedToFavoriteItem] = NotificationsConf.BaseNotification.Create(0), [MsgNoFavoriteItem] = NotificationsConf.BaseNotification.Create(1), [MsgRemovedFromFavoriteItem] = NotificationsConf.BaseNotification.Create(0), [BuyLimitReached] = NotificationsConf.BaseNotification.Create(1), [DailyBuyLimitReached] = NotificationsConf.BaseNotification.Create(1), [UIMsgShopInInitialization] = NotificationsConf.BaseNotification.Create(1), [NoILError] = NotificationsConf.BaseNotification.Create(1), [NoUseDuel] = NotificationsConf.BaseNotification.Create(1), [UIDLCItem] = NotificationsConf.BaseNotification.Create(1)
                }
            }
            ;
            [JsonProperty(PropertyName = LangRu ? "Настройки Discord логирования" : "Discord Logging Settings")]
            public DiscordSettings DiscordConfig = new();
            public VersionNumber Version;
#endregion
#region Classes
            public class NotificationsConf {
#region Fields
                [JsonProperty(PropertyName = LangRu ? "Основные уведомления (сообщение – настройки оповещения)" : "General Notifications (message - settings notification)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
                public Dictionary<string, BaseNotification> GeneralNotifications = new();
#endregion
#region Public Methods
                public void ShowNotify(BasePlayer player, string key, int type, params object[] obj) {
                    if (GeneralNotifications.TryGetValue(key, out var targetNotify)) targetNotify.Show(player, key, obj);
                    else Instance?.SendNotify(player, key, type, obj);
                }
#endregion Public Method
#region Classes
                public class BaseNotification {
#region Fields
                    [JsonProperty(PropertyName = LangRu ? "Тип" : "Type")]
                    public int Type;
                    [JsonProperty(PropertyName = LangRu ? "Показывать уведомление?" : "Show notify?")]
                    public bool ShowNotify = true;
#endregion
#region Public Methods
                    public void Show(BasePlayer player, string key, params object[] args) {
                        if (ShowNotify) Instance.SendNotify(player, key, Type, args);
                        else Instance.Reply(player, key, args);
                    }
#endregion
#region Constructors
                    public static BaseNotification Create(int type) {
                        return new BaseNotification {
                            Type = type, ShowNotify = true
                        }
                        ;
                    }
#endregion
                }
#endregion
            }
            public class DiscountConf {
                [JsonProperty(PropertyName = LangRu ? "Включено" : "Enabled")]
                public bool Enabled;
                [JsonProperty(PropertyName = LangRu ? "Скидка (%)" : "Discount (%)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
                public Dictionary<string, int> Discount = new();
                public int GetDiscount(BasePlayer player) {
                    if (!Enabled || Discount == null || Discount.Count == 0) return 0;
                    var result = 0;
                    foreach (var (perm, discount) in Discount) if (discount > result && player.HasPermission(perm)) result = discount;
                    return result;
                }
            }
            public class FormattingConf {
                [JsonProperty(PropertyName = LangRu ? "Формат цены покупки" : "Buy Price Format")]
                public string BuyPriceFormat;
                [JsonProperty(PropertyName = LangRu ? "Формат цены продажи" : "Sell Price Format")]
                public string SellPriceFormat;
                [JsonProperty(PropertyName = LangRu ? "Формат стоимости в корзине" : "Shopping Bag Cost Format")]
                public string ShoppingBagCostFormat;
                [JsonProperty(PropertyName = LangRu ? "Формат баланса" : "Balance Format")]
                public string BalanceFormat;
            }
            public class BuyAgainConf {
                [JsonProperty(PropertyName = LangRu ? "Включено" : "Enabled")]
                public bool Enabled;
                [JsonProperty(PropertyName = LangRu ? "Разрешение (пример: shopru.buyagain)" : "Permission (ex: shop.buyagain)")]
                public string Permission;
                [JsonProperty(PropertyName = LangRu ? "Изображение" : "Image")]
                public string Image;
                public bool HasAccess(BasePlayer player) {
                    return Enabled && (string.IsNullOrEmpty(Permission) || player.HasPermission(Permission));
                }
            }
            public class DiscordSettings {
                [JsonProperty(PropertyName = LangRu ? "Настройки покупки" : "Buy Settings")]
                public DiscordLogSettings Buy = new() {
                    Enabled = false, Webhook = "", Color = 3066993,  // Green
                    Title = "Shop Purchase", FooterIconUrl = string.Empty, FooterText = "{username} bought {item} x{amount} for {price}"
                }
                ;
                [JsonProperty(PropertyName = LangRu ? "Настройки продажи" : "Sell Settings")]
                public DiscordLogSettings Sell = new() {
                    Enabled = false, Webhook = "", Color = 15158332,  // Red
                    Title = "Shop Sale", FooterIconUrl = string.Empty, FooterText = "{username} sold {item} x{amount} for {price}"
                }
                ;
                [JsonProperty(PropertyName = LangRu ? "Настройки переводов" : "Transfer Settings")]
                public DiscordLogSettings Transfer = new() {
                    Enabled = false, Webhook = "", Color = 3447003,  // Blue
                    Title = "Money Transfer", FooterIconUrl = string.Empty, FooterText = "Transferred {amount} from {username} to {targetname}"
                }
                ;
                public class DiscordLogSettings {
                    [JsonProperty(PropertyName = LangRu ? "Включено" : "Enabled")]
                    public bool Enabled;
                    [JsonProperty(PropertyName = LangRu ? "Discord Webhook URL" : "Discord Webhook URL")]
                    public string Webhook;
                    [JsonProperty(PropertyName = LangRu ? "Цвет (Decimal формат)" : "Color (Decimal format)")]
                    public int Color;
                    [JsonProperty(PropertyName = LangRu ? "Заголовок" : "Title")]
                    public string Title;
                    [JsonProperty(PropertyName = LangRu ? "URL иконки футера (для Buy/Sell используется иконка предмета автоматически)" : "Footer icon URL (for Buy/Sell item icon is used automatically)")]
                    public string FooterIconUrl;
                    [JsonProperty(PropertyName = LangRu ? "Текст футера.Переменные Buy/Sell: {username}, {steamid}, {item}, {amount}, {price}.Transfer: {username}, {steamid}, {targetname}, {targetid}, {amount}" : "Footer text.Variables Buy/Sell: {username}, {steamid}, {item}, {amount}, {price}.Transfer: {username}, {steamid}, {targetname}, {targetid}, {amount})")]
                    public string FooterText;
                }
            }
            public enum SortType {
                None, Name, Amount, PriceDecrease, PriceIncrease
            }
#endregion
        }
#region Classes
        public class Localization {
#region Fields
            [JsonProperty(PropertyName = LangRu ? "Включено" : "Enabled")]
            public bool Enabled;
            [JsonProperty(PropertyName = LangRu ? "Текст (язык - текст)" : "Text (language - text)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, string> Messages = new();
#endregion
#region Helpers
            public string GetMessage(BasePlayer player = null) {
                if (Messages.Count == 0) throw new Exception("The use of localization is enabled, but there are no messages!");
                var userLang = "en";
                if (player != null) userLang = Instance.lang.GetLanguage(player.UserIDString);
                if (Messages.TryGetValue(userLang, out var message)) return message;
                return Messages.TryGetValue("en", out message) ? message : Messages.ElementAt(0).Value;
            }
#endregion
        }
        public class SellContainers {
#region Fields
            [JsonProperty(PropertyName = LangRu ? "Включено" : "Enabled")]
            public bool Enabled;
            [JsonProperty(PropertyName = LangRu ? "Доступные Контейнеры (main, belt, wear)" : "Available Containers (main, belt, wear)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<string> Containers = new();
#endregion
#region Helpers
            public List<ItemContainer> GetContainers(BasePlayer player) {
                if (player == null || player.inventory == null) return Pool.Get<List<ItemContainer>>();
                var list = Pool.Get<List<ItemContainer>>();
                foreach (var cont in Containers) switch (cont) {
                    case "main" : {
                        list.Add(player.inventory.containerMain);
                        break;
                    }
                    case "belt" : {
                        list.Add(player.inventory.containerBelt);
                        break;
                    }
                    case "wear" : {
                        list.Add(player.inventory.containerWear);
                        break;
                    }
                }
                return list;
            }
            public Item[] AllItems(BasePlayer player) {
                var containers = GetContainers(player);
                try {
                    var items = new List<Item>();
                    foreach (var itemContainer in containers) items.AddRange(itemContainer.itemList);
                    return items.ToArray();
                }
                finally {
                    Pool.FreeUnmanaged(ref containers);
                }
            }
            public int AllItems(BasePlayer player, List<Item> items) {
                items.Clear();
                var containers = GetContainers(player);
                try {
                    foreach (var itemContainer in containers) items.AddRange(itemContainer.itemList);
                }
                finally {
                    Pool.FreeUnmanaged(ref containers);
                }
                return items.Count;
            }
#endregion
        }
        public class SelectCurrencyUI {
#region Fields
            [JsonProperty(PropertyName = "Use Fullscreen Background (relative to Overlay)?")]
            public bool UseFullscreenBackground;
            [JsonProperty(PropertyName = "Background")]
            public UiElement Background;
            [JsonProperty(PropertyName = "Use Vertical Layout?")]
            public bool UseVerticalLayout;
            [JsonProperty(PropertyName = "Title")]
            public UiElement Title;
            [JsonProperty(PropertyName = "Economy Title")]
            public UiElement EconomyTitle;
            [JsonProperty(PropertyName = "Economy Panel Material")]
            public string EconomyPanelMaterial = string.Empty;
            [JsonProperty(PropertyName = "Economy Panel Sprite")]
            public string EconomyPanelSprite = string.Empty;
            [JsonProperty(PropertyName = "Selected Economy Color")]
            public IColor SelectedEconomyColor = IColor.CreateWhite();
            [JsonProperty(PropertyName = "Unselected Economy Color")]
            public IColor UnselectedEconomyColor = IColor.CreateWhite();
            [JsonProperty(PropertyName = "Economy Width")]
            public float EconomyWidth;
            [JsonProperty(PropertyName = "Economy Height")]
            public float EconomyHeight;
            [JsonProperty(PropertyName = "Economy Margin")]
            public float EconomyMargin;
            [JsonProperty(PropertyName = "Economy Indent")]
            public float EconomyIndent;
            [JsonProperty(PropertyName = "Frame Width")]
            public float FrameWidth;
            [JsonProperty(PropertyName = "Frame Indent")]
            public float FrameIndent;
            [JsonProperty(PropertyName = "Frame Header")]
            public float FrameHeader;
            [JsonProperty(PropertyName = "Close the menu after a currency change?")]
            public bool CloseAfterChange;
#endregion
        }
#region UI.Classes
        public class InterfacePosition {
#region Fields
            [JsonProperty(PropertyName = "AnchorMin (X)")]
            public float AnchorMinX;
            [JsonProperty(PropertyName = "AnchorMin (Y)")]
            public float AnchorMinY;
            [JsonProperty(PropertyName = "AnchorMax (X)")]
            public float AnchorMaxX = 1;
            [JsonProperty(PropertyName = "AnchorMax (Y)")]
            public float AnchorMaxY = 1;
            [JsonProperty(PropertyName = "OffsetMin (X)")]
            public float OffsetMinX;
            [JsonProperty(PropertyName = "OffsetMin (Y)")]
            public float OffsetMinY;
            [JsonProperty(PropertyName = "OffsetMax (X)")]
            public float OffsetMaxX;
            [JsonProperty(PropertyName = "OffsetMax (Y)")]
            public float OffsetMaxY;
#endregion Fields
#region Public Methods
            public float GetAxis(bool isX) {
                if (isX) return OffsetMinX;
                return -OffsetMaxY;
            }
            public void SetVerticalAxis(VerticalConstraint constraint) {
                switch (constraint) {
                    case VerticalConstraint.Center : AnchorMinY = AnchorMaxY = 0.5f;
                    break;
                    case VerticalConstraint.Bottom : AnchorMinY = AnchorMaxY = 0f;
                    break;
                    case VerticalConstraint.Top : AnchorMinY = AnchorMaxY = 1f;
                    break;
                    case VerticalConstraint.Scale : AnchorMinY = 0f;
                    AnchorMaxY = 1f;
                    break;
                }
            }
            public VerticalConstraint GetVerticalAxis() {
                if (Mathf.Approximately(AnchorMinY, AnchorMaxY)) {
                    if (Mathf.Approximately(AnchorMinY, 0.5f)) return VerticalConstraint.Center;
                    if (Mathf.Approximately(AnchorMinY, 0f)) return VerticalConstraint.Bottom;
                    if (Mathf.Approximately(AnchorMinY, 1f)) return VerticalConstraint.Top;
                }
                if (Mathf.Approximately(AnchorMinY, 0) && Mathf.Approximately(AnchorMaxY, 1)) return VerticalConstraint.Scale;
                return VerticalConstraint.Custom;
            }
            public void SetHorizontalAxis(HorizontalConstraint constraint) {
                switch (constraint) {
                    case HorizontalConstraint.Center : AnchorMinX = AnchorMaxX = 0.5f;
                    break;
                    case HorizontalConstraint.Left : AnchorMinX = AnchorMaxX = 0f;
                    break;
                    case HorizontalConstraint.Right : AnchorMinX = AnchorMaxX = 1f;
                    break;
                    case HorizontalConstraint.Scale : AnchorMinX = 0f;
                    AnchorMaxX = 1f;
                    break;
                }
            }
            public HorizontalConstraint GetHorizontalAxis() {
                if (Mathf.Approximately(AnchorMinX, AnchorMaxX)) {
                    if (Mathf.Approximately(AnchorMinX, 0.5f)) return HorizontalConstraint.Center;
                    if (Mathf.Approximately(AnchorMinX, 0f)) return HorizontalConstraint.Left;
                    if (Mathf.Approximately(AnchorMinX, 1f)) return HorizontalConstraint.Right;
                }
                if (Mathf.Approximately(AnchorMinX, 0) && Mathf.Approximately(AnchorMaxX, 1)) return HorizontalConstraint.Scale;
                return HorizontalConstraint.Custom;
            }
            public enum HorizontalConstraint {
                Left, Center, Right, Scale, Custom
            }
            public enum VerticalConstraint {
                Bottom, Center, Top, Scale, Custom
            }
            public void SetAxis(bool isX, float value) {
                if (isX) {
                    var oldX = OffsetMinX;
                    OffsetMinX = value;
                    OffsetMaxX = OffsetMaxX - oldX + value;
                }
                else {
                    var oldY = -OffsetMaxY;
                    OffsetMaxY = -value;
                    OffsetMinY = OffsetMinY + oldY - value;
                }
            }
            public void MoveX(float value) {
                OffsetMinX += value;
                OffsetMaxX += value;
            }
            public void MoveY(float value) {
                OffsetMinY += value;
                OffsetMaxY += value;
            }
            public float GetPadding(int type = 0)  // 0 - left, 1 - right, 2 - top, 3 - bottom
            {
                switch (type) {
                    case 0 : return OffsetMinX;
                    case 1 : return -OffsetMaxX;
                    case 2 : return -OffsetMaxY;
                    case 3 : return OffsetMinY;
                    default : return OffsetMinX;
                }
            }
            public void SetPadding(float? left = null, float? top = null, float? right = null, float? bottom = null) {
                if (left.HasValue) OffsetMinX = left.Value;
                if (right.HasValue) OffsetMaxX = -right.Value;
                if (bottom.HasValue) OffsetMinY = bottom.Value;
                if (top.HasValue) OffsetMaxY = -top.Value;
            }
            public float GetWidth() {
                return OffsetMaxX - OffsetMinX;
            }
            public void SetWidth(float width) {
                if (GetHorizontalAxis() == HorizontalConstraint.Center) {
                    var half = (float) Math.Round(width / 2f, 2);
                    OffsetMinX = -half;
                    OffsetMaxX = half;
                    return;
                }
                OffsetMaxX = OffsetMinX + width;
            }
            public float GetHeight() {
                return OffsetMaxY - OffsetMinY;
            }
            public void SetHeight(float height) {
                if (GetVerticalAxis() == VerticalConstraint.Center) {
                    var half = (float) Math.Round(height / 2f, 2);
                    OffsetMinY = -half;
                    OffsetMaxY = half;
                    return;
                }
                OffsetMaxY = OffsetMinY + height;
            }
            public Rect GetRect() {
                var rect = new Rect();
                ManipulateRect(GetPivot(), rectTransform => rect = rectTransform.rect);
                return rect;
            }
            private Vector2 GetPivot() {
                return Mathf.Approximately(AnchorMinX, 0.5f) ? new Vector2(0.5f, 0.5f) : new Vector2(0f, 1f);
            }
            private void ManipulateRect(Vector2 pivot, Action<RectTransform> callback) {
                var rect = new GameObject().AddComponent<RectTransform>();
                try {
                    rect.pivot = pivot;
                    rect.anchorMin = new Vector2(AnchorMinX, AnchorMinY);
                    rect.anchorMax = new Vector2(AnchorMaxX, AnchorMaxY);
                    rect.offsetMin = new Vector2(OffsetMinX, OffsetMinY);
                    rect.offsetMax = new Vector2(OffsetMaxX, OffsetMaxY);
                    callback?.Invoke(rect);
                    AnchorMinX = rect.anchorMin.x;
                    AnchorMinY = rect.anchorMin.y;
                    AnchorMaxX = rect.anchorMax.x;
                    AnchorMaxY = rect.anchorMax.y;
                    OffsetMinX = rect.offsetMin.x;
                    OffsetMinY = rect.offsetMin.y;
                    OffsetMaxX = rect.offsetMax.x;
                    OffsetMaxY = rect.offsetMax.y;
                }
                finally {
                    UnityEngine.Object.Destroy(rect.gameObject);
                }
            }
#region CuiRectTransformComponent
            [JsonIgnore]
            private CuiRectTransformComponent _cachedRectTransform;
            public CuiRectTransformComponent GetRectTransform() {
                if (_cachedRectTransform != null) return _cachedRectTransform;
                _cachedRectTransform = new CuiRectTransformComponent {
                    AnchorMin = $"{AnchorMinX} {AnchorMinY}", AnchorMax = $"{AnchorMaxX} {AnchorMaxY}", OffsetMin = $"{OffsetMinX} {OffsetMinY}", OffsetMax = $"{OffsetMaxX} {OffsetMaxY}"
                }
                ;
                return _cachedRectTransform;
            }
            public void InvalidateCache() {
                _cachedRectTransform = null;
            }
#endregion
            public CuiRectTransformComponent GetRectTransform(Func<float, float> formatterOffMaxX, Func<float, float> formatterOffMaxY) {
                var oMaxX = OffsetMaxX;
                if (formatterOffMaxX != null) oMaxX = formatterOffMaxX(OffsetMaxX);
                var oMaxY = OffsetMaxY;
                if (formatterOffMaxY != null) oMaxY = formatterOffMaxY(OffsetMaxY);
                return new CuiRectTransformComponent {
                    AnchorMin = $"{AnchorMinX} {AnchorMinY}", AnchorMax = $"{AnchorMaxX} {AnchorMaxY}", OffsetMin = $"{OffsetMinX} {OffsetMinY}", OffsetMax = $"{oMaxX} {oMaxY}"
                }
                ;
            }
            public override string ToString() {
                return JsonConvert.SerializeObject(GetRectTransform(), 0, new JsonSerializerSettings {
                    DefaultValueHandling = DefaultValueHandling.Ignore
                }
                ).Replace("\\n", "\n");
            }
#endregion
#region Constructors
            public static InterfacePosition CreatePosition(float aMinX, float aMinY, float aMaxX, float aMaxY, float oMinX, float oMinY, float oMaxX, float oMaxY) {
                return new InterfacePosition {
                    AnchorMinX = aMinX, AnchorMinY = aMinY, AnchorMaxX = aMaxX, AnchorMaxY = aMaxY, OffsetMinX = oMinX, OffsetMinY = oMinY, OffsetMaxX = oMaxX, OffsetMaxY = oMaxY
                }
                ;
            }
            public static InterfacePosition CreatePosition(string anchorMin = "0 0", string anchorMax = "1 1", string offsetMin = "0 0", string offsetMax = "0 0") {
                var aMinX = float.Parse(anchorMin.Split(' ')[0]);
                var aMinY = float.Parse(anchorMin.Split(' ')[1]);
                var aMaxX = float.Parse(anchorMax.Split(' ')[0]);
                var aMaxY = float.Parse(anchorMax.Split(' ')[1]);
                var oMinX = float.Parse(offsetMin.Split(' ')[0]);
                var oMinY = float.Parse(offsetMin.Split(' ')[1]);
                var oMaxX = float.Parse(offsetMax.Split(' ')[0]);
                var oMaxY = float.Parse(offsetMax.Split(' ')[1]);
                return new InterfacePosition {
                    AnchorMinX = aMinX, AnchorMinY = aMinY, AnchorMaxX = aMaxX, AnchorMaxY = aMaxY, OffsetMinX = oMinX, OffsetMinY = oMinY, OffsetMaxX = oMaxX, OffsetMaxY = oMaxY
                }
                ;
            }
            public static InterfacePosition CreatePosition(CuiRectTransform rectTransform) {
                var aMinX = float.Parse(rectTransform.AnchorMin.Split(' ')[0]);
                var aMinY = float.Parse(rectTransform.AnchorMin.Split(' ')[1]);
                var aMaxX = float.Parse(rectTransform.AnchorMax.Split(' ')[0]);
                var aMaxY = float.Parse(rectTransform.AnchorMax.Split(' ')[1]);
                var oMinX = float.Parse(rectTransform.OffsetMin.Split(' ')[0]);
                var oMinY = float.Parse(rectTransform.OffsetMin.Split(' ')[1]);
                var oMaxX = float.Parse(rectTransform.OffsetMax.Split(' ')[0]);
                var oMaxY = float.Parse(rectTransform.OffsetMax.Split(' ')[1]);
                return new InterfacePosition {
                    AnchorMinX = aMinX, AnchorMinY = aMinY, AnchorMaxX = aMaxX, AnchorMaxY = aMaxY, OffsetMinX = oMinX, OffsetMinY = oMinY, OffsetMaxX = oMaxX, OffsetMaxY = oMaxY
                }
                ;
            }
#endregion Constructors
        }
        public enum CuiElementType {
            Label, Panel, Button, Image, InputField
        }
        [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
        private sealed class TextEditableAttribute : Attribute {
        }
        public class UiElement : InterfacePosition {
#region Fields
            [JsonProperty(PropertyName = "Enabled?")]
            public bool Enabled;
            [JsonProperty(PropertyName = "Visible")]
            public bool Visible = true;
            [JsonProperty(PropertyName = "Name")]
            public string Name = string.Empty;
            [JsonProperty(PropertyName = "Type (Label/Panel/Button/Image)")]
            [JsonConverter(typeof(StringEnumConverter))]
            public CuiElementType Type;
            [JsonProperty(PropertyName = "Color")]
            public IColor Color = new("#FFFFFF", 100);
            [TextEditable]
            [JsonProperty(PropertyName = "Text", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<string> Text = new();
            [JsonProperty(PropertyName = "Font Size")]
            public int FontSize;
            [JsonProperty(PropertyName = "Font")]
            public CuiElementFont Font = CuiElementFont.RobotoCondensedBold;
            [JsonProperty(PropertyName = "Align")]
            [JsonConverter(typeof(StringEnumConverter))]
            public TextAnchor Align;
            [JsonProperty(PropertyName = "Text Color")]
            public IColor TextColor = new("#FFFFFF", 100);
            [JsonProperty(PropertyName = "Command ({user} - user steamid)")]
            public string Command = string.Empty;
            [JsonProperty(PropertyName = "Image")]
            public string Image = string.Empty;
            [JsonProperty(PropertyName = "Cursor Enabled")]
            public bool CursorEnabled;
            [JsonProperty(PropertyName = "Keyboard Enabled")]
            public bool KeyboardEnabled;
            [JsonProperty(PropertyName = "Sprite")]
            public string Sprite = string.Empty;
            [JsonProperty(PropertyName = "Material")]
            public string Material = string.Empty;
#endregion Fields
#region Public Methods
            public new void InvalidateCache() {
                base.InvalidateCache();
                Color?.InvalidateCache();
                TextColor?.InvalidateCache();
            }
            public bool TryGetImage(out string image) {
                if (Type == CuiElementType.Image) if (!string.IsNullOrEmpty(Image)) if (Image.IsURL() || Image.StartsWith("TheMevent/")) {
                    image = Image;
                    return true;
                }
                image = null;
                return false;
            }
            public void Get(ref CuiElementContainer container, BasePlayer player, string parent, string name = null, string destroy = "", string close = "", Func<string, string> textFormatter = null, Func<string, string> cmdFormatter = null, bool needUpdate = false, CuiRectTransformComponent customRectTransform = null) {
                if (!Enabled) return;
                if (string.IsNullOrEmpty(name)) name = CuiHelper.GetGuid();
                if (needUpdate) destroy = string.Empty;
                switch (Type) {
                    case CuiElementType.Label : {
                        var targetText = GetLocalizedText(player);
                        var text = string.Join("\n", targetText).Replace("<br>", "\n");
                        if (textFormatter != null) text = textFormatter(text);
                        container.Add(new CuiElement {
                            Name = name, Parent = parent, DestroyUi = destroy, Update = needUpdate, Components = {
                                new CuiTextComponent {
                                    Text = Visible ? text : string.Empty, Align = Align, Font = GetFontByType(Font), FontSize = FontSize, Color = Visible ? TextColor.Get() : "0 0 0 0"
                                }
                                , customRectTransform ?? GetRectTransform()
                            }
                        }
                        );
                        break;
                    }
                    case CuiElementType.InputField : {
                        var targetText = GetLocalizedText(player);
                        var text = string.Join("\n", targetText).Replace("<br>", "\n");
                        if (textFormatter != null) text = textFormatter(text);
                        container.Add(new CuiElement {
                            Name = name, Parent = parent, DestroyUi = destroy, Update = needUpdate, Components = {
                                new CuiInputFieldComponent {
                                    Text = Visible ? text : string.Empty, Align = Align, Font = GetFontByType(Font), FontSize = FontSize, Color = Visible ? TextColor.Get() : "0 0 0 0", HudMenuInput = true, ReadOnly = true
                                }
                                , customRectTransform ?? GetRectTransform()
                            }
                        }
                        );
                        break;
                    }
                    case CuiElementType.Panel : {
                        var imageElement = new CuiImageComponent {
                            Color = Visible ? Color.Get() : "0 0 0 0"
                        }
                        ;
                        if (!string.IsNullOrEmpty(Sprite)) imageElement.Sprite = Sprite;
                        if (!string.IsNullOrEmpty(Material)) imageElement.Material = Material;
                        var cuiElement = new CuiElement {
                            Name = name, Parent = parent, DestroyUi = destroy, Update = needUpdate, Components = {
                                imageElement, customRectTransform ?? GetRectTransform()
                            }
                        }
                        ;
                        if (CursorEnabled) cuiElement.Components.Add(new CuiNeedsCursorComponent());
                        if (KeyboardEnabled) cuiElement.Components.Add(new CuiNeedsKeyboardComponent());
                        container.Add(cuiElement);
                        break;
                    }
                    case CuiElementType.Button : {
                        var targetCommand = $"{Command}".Replace("{user}", player.UserIDString);
                        if (cmdFormatter != null) targetCommand = cmdFormatter(targetCommand);
                        var btnElement = new CuiButtonComponent {
                            Command = targetCommand, Color = Visible ? Color.Get() : "0 0 0 0", Close = close
                        }
                        ;
                        if (!string.IsNullOrEmpty(Sprite)) btnElement.Sprite = Sprite;
                        if (!string.IsNullOrEmpty(Material)) btnElement.Material = Material;
                        container.Add(new CuiElement {
                            Name = name, Parent = parent, DestroyUi = destroy, Update = needUpdate, Components = {
                                btnElement, customRectTransform ?? GetRectTransform()
                            }
                        }
                        );
                        var targetText = GetLocalizedText(player);
                        var message = string.Join("\n", targetText)?.Replace("<br>", "\n") ?? string.Empty;
                        if (textFormatter != null) message = textFormatter(message);
                        if (!string.IsNullOrEmpty(message)) container.Add(new CuiElement {
                            Parent = name, Components = {
                                new CuiTextComponent {
                                    Text = Visible ? message : string.Empty, Align = Align, Font = GetFontByType(Font), FontSize = FontSize, Color = Visible ? TextColor.Get() : "0 0 0 0"
                                }
                                , customRectTransform ?? new CuiRectTransformComponent()
                            }
                        }
                        );
                        break;
                    }
                    case CuiElementType.Image : {
                        if (string.IsNullOrEmpty(Image)) return;
                        ICuiComponent imageElement;
                        if (Image == "{player_avatar}") {
                            var image = Image;
                            if (textFormatter != null) image = textFormatter(image);
                            imageElement = new CuiRawImageComponent {
                                SteamId = image, Color = Visible ? Color.Get() : "0 0 0 0"
                            }
                            ;
                        }
                        else {
                            if (Image.StartsWith("assets/")) {
                                if (Image.Contains("Linear")) imageElement = new CuiRawImageComponent {
                                    Color = Visible ? Color.Get() : "0 0 0 0", Sprite = Image
                                }
                                ;
                                else imageElement = new CuiImageComponent {
                                    Color = Enabled ? Color.Get() : "0 0 0 0", Sprite = Image
                                }
                                ;
                            }
                            else if (Image.IsURL()) {
                                imageElement = new CuiRawImageComponent {
                                    Png = Instance?.GetImage(Image), Color = Visible ? Color.Get() : "0 0 0 0"
                                }
                                ;
                            }
                            else {
                                var image = Image;
                                if (textFormatter != null) image = textFormatter(image);
                                imageElement = new CuiRawImageComponent {
                                    Png = Instance?.GetImage(image), Color = Visible ? Color.Get() : "0 0 0 0"
                                }
                                ;
                            }
                        }
                        var cuiElement = new CuiElement {
              
// ... [Code preview truncated due to length. Full source in attached file] ...

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