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

FREE Shop : 2.4.12 2.4.12

Нет прав для скачивания
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.12")]
    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);

       
// ... [Code preview truncated due to length. Full source in attached file] ...

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