C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// #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.UI;
using Debug = UnityEngine.Debug;
using Global = Rust.Global;
using Random = UnityEngine.Random;
#if CARBON
using Carbon.Base;
using Carbon.Modules;
#endif
namespace Oxide.Plugins {
[Info("Shop", "Mevent", "2.1.0")]
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 _enabledImageLibrary, _enabledServerPanel;
#if CARBON
private ImageDatabaseModule imageDatabase;
#endif
private const bool LangRu = true;
private readonly Dictionary<int, ShopItem> _shopItems = new();
private readonly Dictionary<ulong, Coroutine> _coroutines = 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", CMD_Main_Console = "UI_Shop";
public const string PermAdmin = "shop.admin";
private const string PermFreeBypass = "shop.free", PermSetVM = "shop.setvm", PermSetNPC = "shop.setnpc";
private const int _itemsPerTick = 10;
private readonly Dictionary<ulong, NPCShop> _openedShopsNPC = new();
private readonly Dictionary<ulong, Dictionary<string, object>> _itemEditing = new();
private const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
private readonly Dictionary<ulong, Dictionary<string, object>> _categoryEditing = new();
private Timer _updateController;
private readonly HashSet<ulong> _showAllCategories = new();
private bool _isEnabledFavorites;
private (bool status, string message) _initializedStatus = (false, string.Empty);
#endregion
#region Config
private static Configuration _config;
private class Configuration {
#region Fields
[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 ? "Включить логирование в консоль?" : "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 ? "Включить работу с 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 ? "Задержка между загрузкой изображений" : "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 UserInterface {
DisplayType = "Overlay", RoundDigits = 5, Color1 = new IColor("#161617"), Color2 = new IColor("#4B68FF"), Color3 = new IColor("#0E0E10"), Color5 = new IColor("#FF4B4B"), Color7 = new IColor("#CD3838"), Color8 = new IColor("#FFFFFF"), Color9 = new IColor("#4B68FF", 33), Color10 = new IColor("#4B68FF", 50), Color11 = new IColor("#161617", 95), Color12 = new IColor("#161617", 80), Color13 = new IColor("#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),
}
}
;
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) return 0;
var result = 0;
Discount.Where(check => player.HasPermission(check.Key)).ForEach(check => {
if (check.Value > result) result = check.Value;
}
);
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 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 new List<ItemContainer>();
var list = new List<ItemContainer>();
Containers.ForEach(cont => {
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) {
return GetContainers(player).SelectMany(cont => cont.itemList).ToArray();
}
#endregion
}
public class SelectCurrencyUI {
#region Fields
[JsonProperty(PropertyName = "Background")]
public ImageSettings Background;
[JsonProperty(PropertyName = "Title")]
public TextSettings Title;
[JsonProperty(PropertyName = "Economy Title")]
public TextSettings 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 Settings
public class ScrollViewUI {
#region Fields
[JsonProperty(PropertyName = "Scroll Type")]
[JsonConverter(typeof(StringEnumConverter))]
public ScrollType ScrollType;
[JsonProperty(PropertyName = "Movement Type")]
[JsonConverter(typeof(StringEnumConverter))]
public ScrollRect.MovementType MovementType;
[JsonProperty(PropertyName = "Elasticity")]
public float Elasticity;
[JsonProperty(PropertyName = "Deceleration Rate")]
public float DecelerationRate;
[JsonProperty(PropertyName = "Scroll Sensitivity")]
public float ScrollSensitivity;
[JsonProperty(PropertyName = "Minimal Height")]
public float MinHeight;
[JsonProperty(PropertyName = "Additional Height")]
public float AdditionalHeight;
[JsonProperty(PropertyName = "Scrollbar Settings")]
public ScrollBarSettings Scrollbar = new();
#endregion
#region Public Methods
public CuiScrollViewComponent GetScrollView(float totalWidth) {
return GetScrollView(CalculateContentRectTransform(totalWidth));
}
public CuiScrollViewComponent GetScrollView(CuiRectTransform contentTransform) {
var cuiScrollView = new CuiScrollViewComponent {
MovementType = MovementType, Elasticity = Elasticity, DecelerationRate = DecelerationRate, ScrollSensitivity = ScrollSensitivity, ContentTransform = contentTransform, Inertia = true
}
;
switch (ScrollType) {
case ScrollType.Vertical : {
cuiScrollView.Vertical = true;
cuiScrollView.Horizontal = false;
cuiScrollView.VerticalScrollbar = Scrollbar.Get();
break;
}
case ScrollType.Horizontal : {
cuiScrollView.Horizontal = true;
cuiScrollView.Vertical = false;
cuiScrollView.HorizontalScrollbar = Scrollbar.Get();
break;
}
}
return cuiScrollView;
}
public CuiRectTransform CalculateContentRectTransform(float totalWidth) {
CuiRectTransform contentRect;
if (ScrollType == ScrollType.Horizontal) {
contentRect = new CuiRectTransform() {
AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "0 0", OffsetMax = $"{totalWidth} 0"
}
;
}
else {
contentRect = new CuiRectTransform() {
AnchorMin = "0 1", AnchorMax = "1 1", OffsetMin = $"0 -{totalWidth}", OffsetMax = "0 0"
}
;
}
return contentRect;
}
#endregion
#region Classes
public class ScrollBarSettings {
#region Fields
[JsonProperty(PropertyName = "Invert")]
public bool Invert;
[JsonProperty(PropertyName = "Auto Hide")]
public bool AutoHide;
[JsonProperty(PropertyName = "Handle Sprite")]
public string HandleSprite = string.Empty;
[JsonProperty(PropertyName = "Size")]
public float Size;
[JsonProperty(PropertyName = "Handle Color")]
public IColor HandleColor = IColor.CreateWhite();
[JsonProperty(PropertyName = "Highlight Color")]
public IColor HighlightColor = IColor.CreateWhite();
[JsonProperty(PropertyName = "Pressed Color")]
public IColor PressedColor = IColor.CreateWhite();
[JsonProperty(PropertyName = "Track Sprite")]
public string TrackSprite = string.Empty;
[JsonProperty(PropertyName = "Track Color")]
public IColor TrackColor = IColor.CreateWhite();
#endregion
#region Public Methods
public CuiScrollbar Get() {
var cuiScrollbar = new CuiScrollbar() {
Size = Size
}
;
if (Invert) cuiScrollbar.Invert = Invert;
if (AutoHide) cuiScrollbar.AutoHide = AutoHide;
if (!string.IsNullOrEmpty(HandleSprite)) cuiScrollbar.HandleSprite = HandleSprite;
if (!string.IsNullOrEmpty(TrackSprite)) cuiScrollbar.TrackSprite = TrackSprite;
if (HandleColor != null) cuiScrollbar.HandleColor = HandleColor.Get;
if (HighlightColor != null) cuiScrollbar.HighlightColor = HighlightColor.Get;
if (PressedColor != null) cuiScrollbar.PressedColor = PressedColor.Get;
if (TrackColor != null) cuiScrollbar.TrackColor = TrackColor.Get;
return cuiScrollbar;
}
#endregion
}
#endregion
}
public class ImageSettings : InterfacePosition {
#region Fields
[JsonProperty(PropertyName = "Sprite")]
public string Sprite = string.Empty;
[JsonProperty(PropertyName = "Material")]
public string Material = string.Empty;
[JsonProperty(PropertyName = "Image")]
public string Image = string.Empty;
[JsonProperty(PropertyName = "Color")]
public IColor Color = IColor.CreateTransparent();
[JsonProperty(PropertyName = "Cursor Enabled")]
public bool CursorEnabled = false;
[JsonProperty(PropertyName = "Keyboard Enabled")]
public bool KeyboardEnabled = false;
#endregion
#region Private Methods
[JsonIgnore]
private ICuiComponent _imageComponent;
public ICuiComponent GetImageComponent() {
if (_imageComponent != null) return _imageComponent;
if (!string.IsNullOrEmpty(Image)) {
var rawImage = new CuiRawImageComponent {
Png = _instance.GetImage(Image), Color = Color.Get
}
;
if (!string.IsNullOrEmpty(Sprite)) rawImage.Sprite = Sprite;
if (!string.IsNullOrEmpty(Material)) rawImage.Material = Material;
_imageComponent = rawImage;
}
else {
var image = new CuiImageComponent {
Color = Color.Get,
}
;
if (!string.IsNullOrEmpty(Sprite)) image.Sprite = Sprite;
if (!string.IsNullOrEmpty(Material)) image.Material = Material;
_imageComponent = image;
}
return _imageComponent;
}
#endregion
#region Public Methods
public bool TryGetImageURL(out string url) {
if (!string.IsNullOrWhiteSpace(Image) && Image.IsURL()) {
url = Image;
return true;
}
url = null;
return false;
}
public CuiElement GetImage(string parent, string name = null, string destroyUI = null) {
if (string.IsNullOrEmpty(name)) name = CuiHelper.GetGuid();
var element = new CuiElement {
Name = name, Parent = parent, DestroyUi = destroyUI, Components = {
GetImageComponent(), GetRectTransform()
}
}
;
if (CursorEnabled) element.Components.Add(new CuiNeedsCursorComponent());
if (KeyboardEnabled) element.Components.Add(new CuiNeedsKeyboardComponent());
return element;
}
#endregion
#region Constructors
public ImageSettings() {
}
public ImageSettings(string imageURL, IColor color, InterfacePosition position) : base(position) {
Image = imageURL;
Color = color;
}
#endregion
}
public class ButtonSettings : TextSettings {
#region Fields
[JsonProperty(PropertyName = "Button Color")]
public IColor ButtonColor = IColor.CreateWhite();
[JsonProperty(PropertyName = "Sprite")]
public string Sprite = string.Empty;
[JsonProperty(PropertyName = "Material")]
public string Material = string.Empty;
[JsonProperty(PropertyName = "Image")]
public string Image = string.Empty;
[JsonProperty(PropertyName = "Image Color")]
public IColor ImageColor = IColor.CreateWhite();
[JsonProperty(PropertyName = "Use custom image position settings?")]
public bool UseCustomPositionImage = false;
[JsonProperty(PropertyName = "Custom image position settings")]
public InterfacePosition ImagePosition = CreateFullStretch();
#endregion
#region Public Methods
public bool TryGetImageURL(out string url) {
if (!string.IsNullOrWhiteSpace(Image) && Image.IsURL()) {
url = Image;
return true;
}
url = null;
return false;
}
public List<CuiElement> GetButton(string msg, string cmd, string parent, string name = null, string destroyUI = null, string close = null) {
if (string.IsNullOrEmpty(name)) name = CuiHelper.GetGuid();
var list = new List<CuiElement>();
var btn = new CuiButtonComponent {
Color = ButtonColor.Get
}
;
if (!string.IsNullOrEmpty(cmd)) btn.Command = cmd;
if (!string.IsNullOrEmpty(close)) btn.Close = close;
if (!string.IsNullOrEmpty(Sprite)) btn.Sprite = Sprite;
if (!string.IsNullOrEmpty(Material)) btn.Material = Material;
list.Add(new CuiElement {
Name = name, Parent = parent, DestroyUi = destroyUI, Components = {
btn, GetRectTransform()
}
}
);
if (!string.IsNullOrEmpty(Image)) {
list.Add(new CuiElement {
Parent = name, Components = {
(Image.StartsWith("assets/") ? new CuiImageComponent {
Color = ImageColor.Get, Sprite = Image
}
: new CuiRawImageComponent {
Color = ImageColor.Get, Png = _instance.GetImage(Image)
}
), UseCustomPositionImage && ImagePosition != null ? ImagePosition?.GetRectTransform() : new CuiRectTransformComponent()
}
}
);
}
else {
if (!string.IsNullOrEmpty(msg)) list.Add(new CuiElement {
Parent = name, Components = {
GetTextComponent(msg), new CuiRectTransformComponent()
}
}
);
}
return list;
}
#endregion
}
public class TextSettings : InterfacePosition {
#region Fields
[JsonProperty(PropertyName = "Font Size")]
public int FontSize = 12;
[JsonProperty(PropertyName = "Is Bold?")]
public bool IsBold = false;
[JsonProperty(PropertyName = "Align")]
[JsonConverter(typeof(StringEnumConverter))]
public TextAnchor Align = TextAnchor.UpperLeft;
[JsonProperty(PropertyName = "Color")]
public IColor Color = IColor.CreateWhite();
#endregion Fields
#region Public Methods
public CuiTextComponent GetTextComponent(string msg) {
return new CuiTextComponent {
Text = msg ?? string.Empty, FontSize = FontSize, Font = IsBold ? "robotocondensed-bold.ttf" : "robotocondensed-regular.ttf", Align = Align, Color = Color.Get
}
;
}
public CuiElement GetText(string msg, string parent, string name = null, string destroyUI = null) {
if (string.IsNullOrEmpty(name)) name = CuiHelper.GetGuid();
return new CuiElement {
Name = name, Parent = parent, DestroyUi = destroyUI, Components = {
GetTextComponent(msg), GetRectTransform()
}
}
;
}
#endregion
}
public class InterfacePosition {
#region Fields
[JsonProperty(PropertyName = "AnchorMin")]
public string AnchorMin = "0 0";
[JsonProperty(PropertyName = "AnchorMax")]
public string AnchorMax = "1 1";
[JsonProperty(PropertyName = "OffsetMin")]
public string OffsetMin = "0 0";
[JsonProperty(PropertyName = "OffsetMax")]
public string OffsetMax = "0 0";
#endregion
#region Cache
[JsonIgnore]
private CuiRectTransformComponent _position;
#endregion
#region Public Methods
public CuiRectTransformComponent GetRectTransform() {
if (_position != null) return _position;
var rect = new CuiRectTransformComponent();
if (!string.IsNullOrEmpty(AnchorMin)) rect.AnchorMin = AnchorMin;
if (!string.IsNullOrEmpty(AnchorMax)) rect.AnchorMax = AnchorMax;
if (!string.IsNullOrEmpty(OffsetMin)) rect.OffsetMin = OffsetMin;
if (!string.IsNullOrEmpty(OffsetMax)) rect.OffsetMax = OffsetMax;
_position = rect;
return _position;
}
#endregion
#region Constructors
public InterfacePosition() {
}
public InterfacePosition(InterfacePosition other) {
AnchorMin = other.AnchorMin;
AnchorMax = other.AnchorMin;
OffsetMin = other.AnchorMin;
OffsetMax = other.AnchorMin;
}
public static InterfacePosition CreatePosition(float aMinX, float aMinY, float aMaxX, float aMaxY, float oMinX, float oMinY, float oMaxX, float oMaxY) {
return new InterfacePosition {
AnchorMin = $"{aMinX} {aMinY}", AnchorMax = $"{aMaxX} {aMaxY}", OffsetMin = $"{oMinX} {oMinY}", OffsetMax = $"{oMaxX} {oMaxY}"
}
;
}
public static InterfacePosition CreatePosition(string anchorMin = "0 0", string anchorMax = "1 1", string offsetMin = "0 0", string offsetMax = "0 0") {
return new InterfacePosition {
AnchorMin = anchorMin, AnchorMax = anchorMax, OffsetMin = offsetMin, OffsetMax = offsetMax,
}
;
}
public static InterfacePosition CreatePosition(CuiRectTransform rectTransform) {
return new InterfacePosition {
AnchorMin = rectTransform.AnchorMin, AnchorMax = rectTransform.AnchorMax, OffsetMin = rectTransform.OffsetMin, OffsetMax = rectTransform.OffsetMax,
}
;
}
public static InterfacePosition CreateFullStretch() {
return new InterfacePosition {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0",
}
;
}
public static InterfacePosition CreateCenter() {
return new InterfacePosition {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "0 0", OffsetMax = "0 0",
}
;
}
#endregion Constructors
}
public class CheckBoxSettings {
[JsonProperty(PropertyName = "Background")]
public ImageSettings Background;
[JsonProperty(PropertyName = "Checkbox")]
public ButtonSettings CheckboxButton;
[JsonProperty(PropertyName = "Checkbox Size")]
public float CheckboxSize;
[JsonProperty(PropertyName = "Checkbox Color")]
public IColor CheckboxColor;
[JsonProperty(PropertyName = "Title")]
public TextSettings Title;
}
public class IColor {
#region Fields
[JsonProperty(PropertyName = "HEX", NullValueHandling = NullValueHandling.Include)]
public string Hex;
[JsonProperty(PropertyName = "Opacity (0 - 100)", NullValueHandling = NullValueHandling.Include)]
public float Alpha;
#endregion
#region Cache
[JsonIgnore]
private string _color;
[JsonIgnore]
public string Get {
get {
if (string.IsNullOrEmpty(_color)) _color = GetColor();
return _color;
}
}
private string GetColor() {
if (string.IsNullOrEmpty(Hex)) Hex = "#FFFFFF";
var str = Hex.Trim('#');
if (str.Length != 6) throw new Exception(Hex);
var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
return $"{(double) r / 255} {(double) g / 255} {(double) b / 255} {Alpha / 100}";
}
#endregion
#region Constructors
public IColor() {
}
public IColor(string hex, float alpha = 100) {
Hex = hex;
Alpha = alpha;
}
public static IColor Create(string hex, float alpha = 100) {
return new IColor(hex, alpha);
}
public static IColor CreateTransparent() {
return new IColor("#000000", 0);
}
public static IColor CreateWhite() {
return new IColor("#FFFFFF", 100);
}
public static IColor CreateBlack() {
return new IColor("#000000", 100);
}
#endregion
}
#endregion
private class CustomVendingEntry {
#region Fields
[JsonProperty(PropertyName = LangRu ? "Разрешение" : "Permissions")]
public string Permission;
[JsonProperty(PropertyName = LangRu ? "Категории (Названия) [* - все]" : "Categories (Titles) [* - all]", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> Categories;
#endregion
}
private class WipeSettings {
#region Fields
[JsonProperty(PropertyName = LangRu ? "Сброс задержек?" : "Wipe Cooldowns?")]
public bool Cooldown;
[JsonProperty(PropertyName = LangRu ? "Сброс игроков?" : "Wipe Players?")]
public bool Players;
[JsonProperty(PropertyName = LangRu ? "Сброс лимитов" : "Wipe Limits?")]
public bool Limits;
#endregion
}
private class UserInterface {
#region Fields
[JsonProperty(PropertyName = LangRu ? "Тип отображения (Overlay/Hud)" : "Display type (Overlay/Hud)")]
public string DisplayType;
[JsonProperty(PropertyName = LangRu ? "Количество цифр после десятичной точки для округления цен" : "Number of digits after decimal point for rounding prices")]
public int RoundDigits;
[JsonProperty(PropertyName = LangRu ? "Цвет 1" : "Color 1")]
public IColor Color1;
[JsonProperty(PropertyName = LangRu ? "Цвет 2" : "Color 2")]
public IColor Color2;
[JsonProperty(PropertyName = LangRu ? "Цвет 3" : "Color 3")]
public IColor Color3;
[JsonProperty(PropertyName = LangRu ? "Цвет 5" : "Color 5")]
public IColor Color5;
[JsonProperty(PropertyName = LangRu ? "Цвет 7" : "Color 7")]
public IColor Color7;
[JsonProperty(PropertyName = LangRu ? "Цвет 8" : "Color 8")]
public IColor Color8;
[JsonProperty(PropertyName = LangRu ? "Цвет 9" : "Color 9")]
public IColor Color9;
[JsonProperty(PropertyName = LangRu ? "Цвет 10" : "Color 10")]
public IColor Color10;
[JsonProperty(PropertyName = LangRu ? "Цвет 11" : "Color 11")]
public IColor Color11;
[JsonProperty(PropertyName = LangRu ? "Цвет 12" : "Color 12")]
public IColor Color12;
[JsonProperty(PropertyName = LangRu ? "Цвет 13" : "Color 13")]
public IColor Color13;
#endregion
}
public enum ScrollType {
Horizontal, Vertical
}
#region Font
private enum CuiElementFont {
RobotoCondensedBold, RobotoCondensedRegular, DroidSansMono, PermanentMarker,
}
private static string GetFontByType(CuiElementFont fontType) {
switch (fontType) {
case CuiElementFont.RobotoCondensedBold : return "robotocondensed-bold.ttf";
case CuiElementFont.RobotoCondensedRegular : return "robotocondensed-regular.ttf";
case CuiElementFont.DroidSansMono : return "droidsansmono.ttf";
case CuiElementFont.PermanentMarker : return "permanentmarker.ttf";
default : throw new ArgumentOutOfRangeException(nameof(fontType), fontType, null);
}
}
private static CuiElementFont GetFontTypeByFont(string font) {
switch (font) {
case "robotocondensed-bold.ttf" : return CuiElementFont.RobotoCondensedBold;
case "robotocondensed-regular.ttf" : return CuiElementFont.RobotoCondensedRegular;
case "droidsansmono.ttf" : return CuiElementFont.DroidSansMono;
case "permanentmarker.ttf" : return CuiElementFont.PermanentMarker;
default : throw new ArgumentOutOfRangeException(nameof(font), font, null);
}
}
#endregion
private class NPCShop {
#region Fields
[JsonProperty(PropertyName = LangRu ? "Разрешение" : "Permission")]
public string Permission;
[JsonProperty(PropertyName = LangRu ? "Категории [* - все]" : "Categories (Titles) [* - all]", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> Categories;
#endregion
#region Cache
[JsonIgnore]
public string BotID;
#endregion
}
private class ShopCategory : ICloneable, IDisposable {
#region Fields
[JsonProperty(PropertyName = LangRu ? "Включено" : "Enabled")]
public bool Enabled;
[JsonProperty(PropertyName = LangRu ? "Тип категории" : "Category Type")]
[JsonConverter(typeof(StringEnumConverter))]
public Type CategoryType = Type.None;
[JsonProperty(PropertyName = LangRu ? "Название" : "Title")]
public string Title;
[JsonProperty(PropertyName = LangRu ? "Разрешение" : "Permission")]
public string Permission;
[JsonProperty(PropertyName = LangRu ? "Тип сортировки" : "Sort Type")]
[JsonConverter(typeof(StringEnumConverter))]
public Configuration.SortType SortType = Configuration.SortType.None;
[JsonProperty(PropertyName = LangRu ? "Предметы" : "Items", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ShopItem> Items = new();
[JsonProperty(PropertyName = LangRu ? "Локализация" : "Localization")]
public Localization Localization = new();
#endregion
#region Cache
[JsonIgnore]
private int _id = -1;
[JsonIgnore]
public int ID {
get {
if (_id == -1) _id = Random.Range(0, int.MaxValue);
return _id;
}
}
[JsonIgnore]
private List<ShopItem> _sortedItems;
[JsonIgnore]
public List<ShopItem> GetItems {
get {
switch (SortType) {
case Configuration.SortType.None : return Items;
default : if (_sortedItems == null) SortItems();
return _sortedItems;
}
}
}
#endregion
#region Helpers
#region Moving
#region Categories
public void MoveCategoryUp() {
var index = _itemsData.Shop.IndexOf(this);
if (index > 0 && index < _itemsData.Shop.Count) {
(_itemsData.Shop[index], _itemsData.Shop[index - 1]) = (_itemsData.Shop[index - 1], _itemsData.Shop[index]);
// Swap
}
}
public void MoveCategoryDown() {
var index = _itemsData.Shop.IndexOf(this);
if (index >= 0 && index < _itemsData.Shop.Count - 1) {
(_itemsData.Shop[index], _itemsData.Shop[index + 1]) = (_itemsData.Shop[index + 1], _itemsData.Shop[index]);
}
}
#endregion
#region Items
public void MoveItemRight(ShopItem item) {
var index = Items.IndexOf(item);
if (index >= 0 && index < Items.Count - 1) {
(Items[index], Items[index + 1]) = (Items[index + 1], Items[index]);
// Swap
}
}
public void MoveItemLeft(ShopItem item) {
var index = Items.IndexOf(item);
if (index > 0 && index < Items.Count) {
(Items[index], Items[index - 1]) = (Items[index - 1], Items[index]);
// Swap
}
}
#endregion
#endregion
public List<ShopItem> GetShopItems(
// ... [Code preview truncated due to length. Full source in attached file] ...