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

FREE JStacks : 1.2.3 1.2.3

Нет прав для скачивания
C#:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Core;
using UnityEngine;
using Newtonsoft.Json;
using Instancing;
using UnityEngine.PlayerLoop;
using Facepunch.Math; 
using UnityEngine.UI;
using Facepunch.Nexus;

namespace Oxide.Plugins
{
    [Info("JStacks", "cr1sTioJ_ST1_(FIX)", "1.2.3")]
    [Description("Plugin allows you to change stack sizes of items")]
    class JStacks : RustPlugin
    {
        #region Global Variables
        public static JStacks Instance;
        private string InitialLayer = "Ui_Stacks";
        private string PermissionUse = "jstacks.use";

        private ConfigData _config;
        private Dictionary<string, int> _defaultStackSizes = new Dictionary<string, int>();
        private Dictionary<string, int> _customStackSizes = new Dictionary<string, int>();
        private Dictionary<string, List<string>> _categoryItemsList = new Dictionary<string, List<string>>();
        private Dictionary<ulong, Timer> _playersNotifyTimers = new Dictionary<ulong, Timer>();
        private Dictionary<ulong, ChoiceOption> _playersChoiceOptions = new Dictionary<ulong, ChoiceOption>();
        private Dictionary<ulong, List<string>> _playersSelectedItems = new Dictionary<ulong, List<string>>();
        private Dictionary<ulong, int> _playersAmounts = new Dictionary<ulong, int>();
        private Dictionary<string, string> _namesWithSeveralWords = new Dictionary<string, string>();

        private enum ChoiceOption
        {
            Single,
            Multiple
        }

        #endregion

        #region Config
        private class ConfigData
        {
            [JsonProperty("Default icons for categories (in-game only)")]
            public Dictionary<string, string> categoryIcons;

            [JsonProperty("Can admins use command")]
            public bool canAdminUse;

            [JsonProperty("Command to open the menu")]
            public string menuCommand;

            [JsonProperty("Command to set stack size of an item in your hands")]
            public string setHandStackCommand;
        }

        protected override void LoadDefaultConfig()
        {
            Config.WriteObject(new ConfigData()
            {
                categoryIcons = new Dictionary<string, string>()
                {
                    ["Weapon"] = "assets/icons/weapon.png",
                    ["Construction"] = "assets/icons/construction.png",
                    ["Items"] = "assets/icons/extinguish.png",
                    ["Resources"] = "assets/icons/community_servers.png", 
                    ["Attire"] = "assets/icons/community_servers.png",
                    ["Tool"] = "assets/icons/tools.png",
                    ["Medical"] = "assets/icons/medical.png",
                    ["Food"] = "assets/icons/food_cooked.png",
                    ["Ammunition"] = "assets/icons/ammunition.png", 
                    ["Traps"] = "assets/icons/traps.png",
                    ["Component"] = "assets/icons/open.png",
                    ["Electrical"] = "assets/icons/electric.png",
                    ["Fun"] = "assets/icons/fun_alt.png",
                    ["Misc"] = "assets/icons/menu_dots.png"                  
                },
                canAdminUse = true,
                menuCommand = "stacks",
                setHandStackCommand = "sethandstack"
            }, true);
        }

        #endregion

        #region Commands

        [ConsoleCommand("jstacks.section")]
        private void CmdChangeSection(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;
            if (!CanUse(player)) return;
            var categoryName = arg.GetString(0, "");

            UpdateLayers(player, categoryName);
        }

        [ConsoleCommand("jstack.changer.call")]
        private void CmdChangerCall(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;
            if (!CanUse(player)) return;
            var itemName = arg.FullString;

            ChangerCall(player, itemName);
        }

        [ConsoleCommand("jstacks.setstack")]
        private void CmdSetStack(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            var itemName = arg.GetString(0, "");
            var stack = arg.GetInt(1, 0);
            if (_namesWithSeveralWords.ContainsKey(itemName))
            {
                itemName = _namesWithSeveralWords[itemName];
                stack = arg.GetInt(arg.Args.Length - 1, 0);
            }
            var itemDef = ItemManager.FindItemDefinition(itemName);

            if (itemDef != null)
            {
                if (stack == itemDef.stackable)
                {
                    CuiHelper.DestroyUi(player, InitialLayer + $".Item.Changer");
                    return;
                }
            }

            if (player == null)
            {
                if (SetStack(itemName, stack))
                    arg.Reply = string.Format(GetMsg("STACK_CHANGED"), itemName, stack);
                else
                    arg.Reply = string.Format(GetMsg("STACK_NOT_CHANGED"), itemName);
                return;
            }

            if (CanUse(player))
            {
                if (SetStack(itemName, stack))
                    Notify(player, string.Format(GetMsg("STACK_CHANGED", player), itemName, stack), "green");
                else
                    Notify(player, string.Format(GetMsg("STACK_NOT_CHANGED", player), itemName), "red");

                if (itemDef != null)
                {
                    FillMenuWithItems(player, itemDef.category.ToString());
                }
            }
        }
        
		[ConsoleCommand("jstacks.request.restore")]
        private void CmdRestoreRequestStacks(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;
            if (!CanUse(player)) return;

            ShowConfirmMenu(player, GetMsg("RESTORE_MAIN_QUESTION", player), "jstacks.restore");
        }

		[ConsoleCommand("jstacks.restore")]
        private void CmdRestoreStacks(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null)
            {
                RestoreStackSizes();
                arg.Reply = GetMsg("RESTORED");
                return;
            }
            if (CanUse(player))
            {
                RestoreStackSizes();
                InitializeLayers(player);
                Notify(player, GetMsg("RESTORED", player));
            }
        }

        [ConsoleCommand("jstacks.categorychanger.call")]
        private void CmdCategoryChangerCall(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            var categoryName = arg.GetString(0, "");
            if (player == null) return;
            if (!CanUse(player)) return;
            if (string.IsNullOrEmpty(categoryName)) return;

            CategoryChangerCall(player, categoryName);
        }

        [ConsoleCommand("jstacks.category.changestack")]
        private void CmdCategoryChangeStack(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;
            if (!CanUse(player)) return;
            string categoryName = arg.GetString(0, "");
            if (string.IsNullOrEmpty(categoryName)) return;
            int stackSize = 0;
            if (_playersAmounts.ContainsKey(player.userID))
            {
                stackSize = _playersAmounts[player.userID];
            }
            if (stackSize <= 0) 
            {
                Notify(player, GetMsg("ERROR_WRONG_STACK_SIZE", player),"red");
                return;
            }
            var categoryItems = _categoryItemsList[categoryName];
            foreach (var item in categoryItems)
            {
                SetStack(item, stackSize);
            }
            SaveCustomStackSizes();
            UpdateLayers(player, categoryName);
            Notify(player, string.Format(GetMsg("CATEGORY_STACK_SIZE_CHANGED", player), categoryName, stackSize), "green");
        }

        [ConsoleCommand("jstacks.multiple.toggle")]
        private void CmdMultipleToggle(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            var categoryName = arg.GetString(0, "");
            if (player == null) return;
            if (!CanUse(player)) return;
            if (string.IsNullOrEmpty(categoryName)) return;

            _playersChoiceOptions[player.userID] = _playersChoiceOptions[player.userID] == ChoiceOption.Single ? ChoiceOption.Multiple : ChoiceOption.Single;

            UpdateLayers(player, categoryName);
            UpdateMultipleButton(player);
        }

        [ConsoleCommand("jstacks.setforselected")]
        private void cmdSetForSelected(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;
            if (!CanUse(player)) return;

            var stack = 0;
            if (_playersAmounts.ContainsKey(player.userID))
            {
                stack = _playersAmounts[player.userID];
            }

            if (stack <= 0)
            {
                Notify(player, GetMsg("ERROR_WRONG_STACK_SIZE", player), "red");
                return;
            }
            
            if (!_playersSelectedItems.ContainsKey(player.userID))
            {
                Notify(player, GetMsg("ERROR_NO_ITEMS_SELECTED", player), "red");
                return;
            }

            if (_playersSelectedItems[player.userID].Count == 0)
            {
                Notify(player, GetMsg("ERROR_NO_ITEMS_SELECTED", player), "red");
                return;
            }

            foreach (var item in _playersSelectedItems[player.userID])
            {
                SetStack(item, stack);
            }

            Notify(player, GetMsg("MULTIPLE_CHANGE_SUCCESS", player).Replace("{0}", _playersSelectedItems[player.userID].Count.ToString()), "green");
            _playersChoiceOptions[player.userID] = ChoiceOption.Single;
            var category = _categoryItemsList.FirstOrDefault(
                x => x.Value.Contains(_playersSelectedItems[player.userID].First())
            ).Key;
            _playersSelectedItems[player.userID].Clear();
            UpdateLayers(player, category);
            UpdateMultipleButton(player);
            SaveCustomStackSizes();
        }

        [ConsoleCommand("jstacks.changeamount")]
        private void CmdChangeAmount(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            var amount = arg.GetInt(0, 0);
            if (player == null) return;
            if (!CanUse(player)) return;

            _playersAmounts[player.userID] = amount;
        }

        private void SetHandStack(BasePlayer player, string command, string[] args)
        {
            if (!CanUse(player))
            {
                SendReply(player, GetMsg("ERROR_NO_PERMISSION", player)); 
                return;
            }
            if (args == null || args.Length < 1)
            {
                SendReply(player, GetMsg("ERROR_NO_NEW_STACK_SIZE", player)); 
                return;
            }
            int stack = 0;
            if (!int.TryParse(args[0], out stack))
            {
                SendReply(player, GetMsg("ERROR_NO_NEW_STACK_SIZE", player));
                return;
            }
            var item = player.GetActiveItem();
            if (item == null)
            {
                SendReply(player, GetMsg("NO_ITEM_IN_HANDS", player));
                return;
            }
            if (SetStack(item.info.shortname, stack))
            {
                SendReply(player, string.Format(GetMsg("STACK_CHANGED", player), item.info.shortname, stack));
            }
            else
            {
                SendReply(player, string.Format(GetMsg("STACK_NOT_CHANGED", player), item.info.shortname));
            }
        }

        #endregion

        #region Methods 
        private bool CanUse(BasePlayer player)
        {
            return permission.UserHasPermission(player.UserIDString, PermissionUse) 
                || (_config.canAdminUse && player.IsAdmin);
        }
        private void SaveCustomStackSizes()
        {
            Interface.Oxide.DataFileSystem.WriteObject($"{this.Title}/CustomStackSizes", _customStackSizes);
        }
        private void LoadCustomStackSizes()
        {
            var storedData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, int>>($"{this.Title}/CustomStackSizes");
            if (storedData != null)
            {
                _customStackSizes = storedData;
                foreach (var item in _customStackSizes)
                {
                    if (!ItemManager.itemDictionaryByName.ContainsKey(item.Key)) continue;
                    ItemManager.itemDictionaryByName[item.Key].stackable = item.Value;
                }
            }
        }
        private void SaveDefaultStackSizes()
        {
            Interface.Oxide.DataFileSystem.WriteObject($"{this.Title}/DefaultStackSizes", _defaultStackSizes);
        }
        private void LoadDefaultStackSizes()
        {
            var storedData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, int>>($"{this.Title}/DefaultStackSizes");
            if (storedData != null && storedData.Count > 0)
            {
                _defaultStackSizes = storedData;
                return;
            }
            foreach (var item in ItemManager.itemList)
            {
                _defaultStackSizes[item.shortname] = item.stackable;
                SaveDefaultStackSizes();
            }
        }

        private void FillCategoryItemsList()
        {
            var processedItems = new HashSet<string>();
            
            foreach (var item in ItemManager.itemList)
            {
                // Handle names with spaces (for multi-word item names)
                if (item.shortname.Contains(" "))
                {
                    string firstWord = item.shortname.Split(' ')[0];
                    if (!_namesWithSeveralWords.ContainsKey(firstWord))
                    {
                        _namesWithSeveralWords[firstWord] = item.shortname;
                    }
                }
                
                // Handle category items list
                string category = item.category.ToString();
                if (!_categoryItemsList.ContainsKey(category))
                {
                    _categoryItemsList[category] = new List<string>();
                }
                
                // Only add each shortname once per category
                if (!processedItems.Contains($"{category}_{item.shortname}"))
                {
                    _categoryItemsList[category].Add(item.shortname);
                    processedItems.Add($"{category}_{item.shortname}");
                }
            }
        }
        private void RestoreStackSizes()
        {
            foreach (var item in ItemManager.itemList)
            {
                if (_defaultStackSizes.ContainsKey(item.shortname))
                {
                    int defaultSize = _defaultStackSizes[item.shortname];
                    item.stackable = defaultSize;
                }
                else 
                {
                    _defaultStackSizes[item.shortname] = item.stackable;
                }
            }
            _customStackSizes.Clear();
            Log("log", $"Stack sizes restored");
        }
        private bool SetStack(string itemName, int stack)
        {
            if (stack <= 0) return false;
            var itemDef = ItemManager.FindItemDefinition(itemName);
            if (itemDef == null) return false;
            itemDef.stackable = stack;
            _customStackSizes[itemDef.shortname] = stack;
            Log("log", $"{itemName} stack size changed to {stack}");
            return true;
        }

        private void Log(string filename, string text)
        {
            DateTime currentTime = DateTime.Now;
            string formattedTime = currentTime.ToString("dd.MM.yyyy HH:mm:ss");

            LogToFile(filename, $"[{formattedTime}] {text}", this);
        }
        public static string HexToColor(string hex, double alpha)
        {
            if (hex.Contains(" ")) return hex;

            hex = hex.Replace("#", "");

            float r = (float)System.Convert.ToInt32(hex.Substring(0, 2), 16) / 255f;
            float g = (float)System.Convert.ToInt32(hex.Substring(2, 2), 16) / 255f;
            float b = (float)System.Convert.ToInt32(hex.Substring(4, 2), 16) / 255f;

            return $"{r} {g} {b} {alpha}";
        }
        #endregion

        #region Hooks
        private void OnServerInitialized(bool initial)
        {
            Instance = this;
            permission.RegisterPermission(PermissionUse, this);
            _config = Config.ReadObject<ConfigData>();
            LoadMessages();
            FillCategoryItemsList();
            LoadDefaultStackSizes();
            LoadCustomStackSizes();
            cmd.AddChatCommand(_config.menuCommand, this, OpenMenu);
            cmd.AddChatCommand(_config.setHandStackCommand, this, SetHandStack);
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                CuiHelper.DestroyUi(player, InitialLayer);
            }
            SaveDefaultStackSizes();
            SaveCustomStackSizes();
        }
        #endregion

        #region Cui
        private void OpenMenu(BasePlayer player, string command, string[] args)
        {
            if (!CanUse(player))
            {
                SendReply(player, GetMsg("ERROR_NO_PERMISSION", player));
                return;
            }
            InitializeLayers(player);
        }
        private void InitializeLayers(BasePlayer player)
        {
            _playersChoiceOptions[player.userID] = ChoiceOption.Single;

            var elements = new CuiElementContainer();

            elements.Add(new CuiElement()
            {
                Parent = "Overlay",
                Name = InitialLayer,
                DestroyUi = InitialLayer,
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    new CuiImageComponent 
                    {
                        Color = "0.113725491 0.1254902 0.121568628 0.8",
                        Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat",
                        Sprite = "assets/content/ui/ui.background.transparent.radial.psd"
                    }, 
                    new CuiNeedsCursorComponent()
                }
            });

            elements.Add(new CuiElement()
            {
                Parent = InitialLayer,
                Components =
                {
                    new CuiImageComponent
                    {
                        Color = "0.143725491 0.1554902 0.121568628 0.85"  
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0"
                    }
                }
            });

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-250 -248", OffsetMax = "390 248" }, 
                Image = { Color = "0.968627453 0.921568632 0.882352948 0.2", Sprite = "Assets/Content/UI/UI.Background.Tile.psd", ImageType = Image.Type.Tiled }
            }, InitialLayer, InitialLayer + ".Body");

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 5", OffsetMax = "0 -40" }, 
                Image = { Color = "0 0 0 0" }
            }, InitialLayer + ".Body", InitialLayer + ".Container");

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "-175 0", OffsetMax = "-3 0" }, 
                Image = { Color = "0.968627453 0.921568632 0.882352948 0.2", Sprite = "Assets/Content/UI/UI.Background.Tile.psd", ImageType = Image.Type.Tiled }
            }, InitialLayer  + ".Body", InitialLayer + ".NavBar");

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-30 -30", OffsetMax = "-10 -10" },
                Image = { Color = "0.7 0.2219512 0.14682925 1", Sprite = "Assets/Content/UI/UI.Background.Tile.psd", ImageType = Image.Type.Tiled }
            }, InitialLayer + ".Body", InitialLayer + ".CloseButton");

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 5", OffsetMax = "-5 -5" },
                Image = { Color = "1 0.49271604 0.413 1", Sprite = "assets/icons/close.png"}
            }, InitialLayer + ".CloseButton");

            elements.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                Button = { Close = InitialLayer, Color = "0 0 0 0"},
            }, InitialLayer + ".CloseButton");

            for (int i = 0, y = 0; i < _config.categoryIcons.Count; i++, y -= 35)
            {
                var categoryName = _config.categoryIcons.ElementAt(i).Key;
                var categoryIcon = _config.categoryIcons.ElementAt(i).Value; 

                elements.Add(new CuiPanel()
                {
                    RectTransform = { AnchorMin = "0 1", AnchorMax = "1 1", OffsetMin = $"3 {y - 35}", OffsetMax = $"-3 {y - 3}" },
                    Image = { Color = "0.968627453 0.921568632 0.882352948 0.1",}
                }, InitialLayer + ".NavBar", InitialLayer + $".Nav_{categoryName}");

                elements.Add(new CuiPanel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "7 7", OffsetMax = "25 25" },
                    Image = { Color = "0.968627453 0.921568632 0.882352948 0.3686275", Sprite = categoryIcon }
                }, InitialLayer + $".Nav_{categoryName}", InitialLayer + $".Nav.Icon_{categoryName}");

                elements.Add(new CuiLabel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "32 5", OffsetMax = "-5 -5" },
                    Text = { Text = categoryName.ToUpper(), Color = "0.968627453 0.921568632 0.882352948 0.3686275", FontSize = 14, Align = TextAnchor.MiddleLeft } 
                }, InitialLayer + $".Nav_{categoryName}", InitialLayer + $".Nav.Text_{categoryName}");

                elements.Add(new CuiButton()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Button = { Command = $"jstacks.section {categoryName}", Color = "0 0 0 0"},
                }, InitialLayer + $".Nav_{categoryName}");
            }

            elements.Add(new CuiElement()
            {
                Name = InitialLayer + ".ItemList",
                Parent = InitialLayer + ".Container",
                DestroyUi = InitialLayer + ".ItemList",
                Components =
                {
                    new CuiScrollViewComponent 
                    {
                        ContentTransform = new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                        Vertical = true,
                        Elasticity = 0f,
                        Inertia = true,
                        DecelerationRate = 5f,
                        ScrollSensitivity = 35f,
                        MovementType = UnityEngine.UI.ScrollRect.MovementType.Elastic,
                        Horizontal = false,
                        HorizontalScrollbar = null
                    },
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" }
                }
            });

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 0", OffsetMin = "10 5", OffsetMax = "-10 25" },
                Image = { Color = "0.968627453 0.921568632 0.882352948 0.1" }
            }, InitialLayer + ".Body", InitialLayer + $".InfoPanel");

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "3 3", OffsetMax = "17 17" },
                Image = { Color = "0.968627453 0.921568632 0.882352948 0.5686275", Sprite = "assets/icons/info.png"}
            }, InitialLayer + $".InfoPanel");

            elements.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "20 3", OffsetMax = "-5 -3" },
                Text = { Text = GetMsg("TEXT_INFO_PANEL", player).ToUpper(), Color = "0.968627453 0.921568632 0.882352948 0.5686275", FontSize = 9, Align = TextAnchor.MiddleLeft } 
            }, InitialLayer + $".InfoPanel");

            elements.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "10 -30", OffsetMax = "140 -10" },
                Image = { Color = "0.7 0.2219512 0.14682925 1", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat", Sprite = "Assets/Content/UI/UI.Background.Tile.psd", ImageType = Image.Type.Tiled }
            }, InitialLayer + $".Body", InitialLayer + $".RestoreButton");

            elements.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "3 3", OffsetMax = "18 -3" },
                Image = { Color = "1 0.49271604 0.413 1", Sprite = "assets/icons/refresh.png" }
            }, InitialLayer + $".RestoreButton");

            elements.Add(new CuiLabel{
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "24 0", OffsetMax = "0 0" },
                Text = { Text = GetMsg("RESTORE_TEXT", player).ToUpper(), Color = "0.97199994 0.8308799 0.80870396 1", FontSize = 10, Align = TextAnchor.MiddleLeft }
            }, InitialLayer + $".RestoreButton");

            elements.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                Button = { Command = $"jstacks.request.restore", Color = "0 0 0 0" },
            }, InitialLayer + $".RestoreButton");

            elements.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "150 -30", OffsetMax = "280 -10" },
                Image = { Color = "0.4509804 0.5529412 0.27058825 1", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat" }
            }, InitialLayer + $".Body", InitialLayer + $".CategoryChanger");

            elements.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "3 3", OffsetMax = "18 -3" },
                Image = { Color = "0.6164634 0.8113208 0.27171594 1", Sprite = "assets/icons/pet_move.png" }
            }, InitialLayer + $".CategoryChanger");

            elements.Add(new CuiLabel
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "24 0", OffsetMax = "0 0" },
                Text = { Text = GetMsg("CATEGORY_CHANGER_TEXT", player).ToUpper(), Color = "0.7348033 0.8490566 0.53266287 1", FontSize = 10, Align = TextAnchor.MiddleLeft }
            }, InitialLayer + $".CategoryChanger");

            elements.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                Button = { Color = "0 0 0 0" },
            }, InitialLayer + $".CategoryChanger", InitialLayer + $".CategoryChanger.Button");

            elements.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "290 -30", OffsetMax = "420 -10" },
                Image = { Color = "0.11574403 0.3310115 0.4811321 0.5", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat" }
            }, InitialLayer + $".Body", InitialLayer + $".MultiChoice");

            elements.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "3 3", OffsetMax = "18 -3" },
                Image = { Color = "0 0.58914757 1 1", Sprite = "assets/icons/check.png" }
            }, InitialLayer + $".MultiChoice", InitialLayer + $".MultiChoice.Icon");

            elements.Add(new CuiLabel
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "24 0", OffsetMax = "0 0" },
                Text = { Text = GetMsg("MULTIPLE_CHOICE_TITLE", player).ToUpper(), Color = "0.5030705 0.73362494 0.8962264 1", FontSize = 10, Align = TextAnchor.MiddleLeft }
            }, InitialLayer + $".MultiChoice", InitialLayer + $".MultiChoice.Title");

            elements.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                Button = { Color = "0 0 0 0", Command = "jstacks.multiple.toggle" },
            }, InitialLayer + $".MultiChoice", InitialLayer + $".MultiChoice.Button");

            CuiHelper.AddUi(player, elements);
            UpdateLayers(player);
        }

        private void UpdateLayers(BasePlayer player, string categoryName = "")
        {
            CuiHelper.DestroyUi(player, InitialLayer + ".CategoryChangerBackground");
            if (_playersSelectedItems.ContainsKey(player.userID))
            {
                _playersSelectedItems[player.userID].Clear();
            }

            if (categoryName == "")
            {
                categoryName = _config.categoryIcons.ElementAt(0).Key;
            }
            var categoryIcon = _config.categoryIcons[categoryName];

            var elements = new CuiElementContainer();

            elements.Add(new CuiElement()
            {
                Name = InitialLayer + ".ChosenNav",
                Parent = InitialLayer + $".Nav_{categoryName}",
                DestroyUi = InitialLayer + ".ChosenNav",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "-7 -3", OffsetMax = "7 3" },
                    new CuiImageComponent { Color = "0.11574403 0.3310115 0.4811321 1", Material = "assets/content/ui/uibackgroundblur.mat"}
                }
            });

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "5 5", OffsetMax = "31 31" },
                Image = { Color = "0.968627453 0.921568632 0.882352948 0.5686275", Sprite = categoryIcon }
            }, InitialLayer + ".ChosenNav", InitialLayer + $".ChosenNav.Icon");

            elements.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "36 5", OffsetMax = "-5 -5" },
                Text = { Text = categoryName.ToUpper(), Color = "0.968627453 0.921568632 0.882352948 0.6686275", FontSize = 16, Align = TextAnchor.MiddleLeft }
            }, InitialLayer + $".ChosenNav");

            elements.Add(new CuiElement()
            {
                Name = InitialLayer + $".CategoryChanger.Button",
                Update = true,
                Components =
                {
                    new CuiButtonComponent{ Command = "jstacks.categorychanger.call " + categoryName },
                }
            });

            elements.Add(new CuiElement()
            {
                Name =  InitialLayer + $".MultiChoice.Button",
                Update = true,
                Components =
                {
                    new CuiButtonComponent{ Command = "jstacks.multiple.toggle " + categoryName },
                }
            });

            CuiHelper.AddUi(player, elements);
            UpdateMultipleButton(player);
            FillMenuWithItems(player, categoryName);
        }

        private void FillMenuWithItems(BasePlayer player, string categoryName)
{
    var elements = new CuiElementContainer();

    // Берём только реальные видимые предметы категории
    var visibleItems = _categoryItemsList[categoryName]
        .Select(shortname => ItemManager.FindItemDefinition(shortname))
        .Where(itemDef => itemDef != null && !itemDef.hidden)
        .ToList();

    // Настройки сетки
    const int columns = 10;      // сколько предметов в строке
    const float itemSize = 54f;  // размер плитки предмета
    const float spacing = 60f;   // расстояние между плитками
    const float startX = 8f;
    const float startY = 8f;

    int rows = Mathf.CeilToInt(visibleItems.Count / (float)columns);

    // Минимальная высота, чтобы маленькие категории не ломали окно.
    // Если предметов много — высота увеличивается, и появляется нормальный скролл.
    float contentHeight = Mathf.Max(420f, rows * spacing + 20f);

    elements.Add(new CuiElement()
    {
        Name = InitialLayer + ".ItemList",
        Parent = InitialLayer + ".Container",
        DestroyUi = InitialLayer + ".ItemList",
        Components =
        {
            new CuiScrollViewComponent
            {
                ContentTransform = new CuiRectTransformComponent
                {
                    AnchorMin = "0 1",
                    AnchorMax = "1 1",
                    OffsetMin = $"0 -{contentHeight}",
                    OffsetMax = "0 0"
                },
                Vertical = true,
                Horizontal = false,
                Elasticity = 0f,
                Inertia = true,
                DecelerationRate = 0.1f,
                ScrollSensitivity = 35f,
                MovementType = UnityEngine.UI.ScrollRect.MovementType.Elastic,
                HorizontalScrollbar = null
            },
            new CuiRectTransformComponent
            {
                AnchorMin = "0 0",
                AnchorMax = "1 1",
                OffsetMin = "0 30",
                OffsetMax = "0 0"
            }
        }
    });

    // Прозрачный фон внутри списка
    elements.Add(new CuiPanel()
    {
        Image = { Color = "0 0 0 0" },
        RectTransform =
        {
            AnchorMin = "0 1",
            AnchorMax = "1 1",
            OffsetMin = $"0 -{contentHeight}",
            OffsetMax = "0 0"
        }
    }, InitialLayer + ".ItemList");

    for (int i = 0; i < visibleItems.Count; i++)
    {
        var itemDef = visibleItems[i];

        int row = i / columns;
        int col = i % columns;

        float x = startX + col * spacing;
        float y = startY + row * spacing;

        string itemPanelName = InitialLayer + $".Item_{itemDef.shortname}";

        elements.Add(new CuiPanel()
        {
            Image = { Color = "0.968627453 0.921568632 0.882352948 0.1" },
            RectTransform =
            {
                AnchorMin = "0 1",
                AnchorMax = "0 1",
                OffsetMin = $"{x} {-y - itemSize}",
                OffsetMax = $"{x + itemSize} {-y}"
            },
        }, InitialLayer + ".ItemList", itemPanelName);

        elements.Add(new CuiPanel()
        {
            Image = { ItemId = itemDef.itemid },
            RectTransform =
            {
                AnchorMin = "0 0",
                AnchorMax = "1 1",
                OffsetMin = "5 5",
                OffsetMax = "-5 -5"
            },
        }, itemPanelName);

        elements.Add(new CuiButton()
        {
            RectTransform =
            {
                AnchorMin = "0 0",
                AnchorMax = "1 1",
                OffsetMin = "0 0",
                OffsetMax = "0 0"
            },
            Button =
            {
                Command = $"jstack.changer.call {itemDef.shortname}",
                Color = "0 0 0 0"
            },
        }, itemPanelName);

        elements.Add(new CuiLabel()
        {
            RectTransform =
            {
                AnchorMin = "0 0",
                AnchorMax = "1 0",
                OffsetMin = "0 0",
                OffsetMax = "-3 15"
            },
            Text =
            {
                Text = "x" + itemDef.stackable,
                Color = "0.968627453 0.921568632 0.882352948 0.6686275",
                FontSize = 9,
                Align = TextAnchor.MiddleRight,
                Font = "RobotoCondensed-Bold.ttf"
            }
        }, itemPanelName);

        int defaultSize;

        if (_defaultStackSizes.ContainsKey(itemDef.shortname))
        {
            defaultSize = _defaultStackSizes[itemDef.shortname];
        }
        else
        {
            defaultSize = itemDef.stackable;
            _defaultStackSizes[itemDef.shortname] = defaultSize;
        }

        elements.Add(new CuiLabel()
        {
            RectTransform =
            {
                AnchorMin = "0 1",
                AnchorMax = "1 1",
                OffsetMin = "0 -15",
                OffsetMax = "-3 0"
            },
            Text =
            {
                Text = "def." + defaultSize,
                Color = "0.968627453 0.921568632 0.882352948 0.6686275",
                FontSize = 9,
                Align = TextAnchor.MiddleRight,
                Font = "RobotoCondensed-Bold.ttf"
            }
        }, itemPanelName);
    }

    CuiHelper.AddUi(player, elements);
}

		private void ChangerCall(BasePlayer player, string itemName)
        {
            var elements = new CuiElementContainer();
            var itemDef = ItemManager.FindItemDefinition(itemName);

            var choiceOption = _playersChoiceOptions[player.userID];

            if (choiceOption == ChoiceOption.Single)
            {

                elements.Add(new CuiPanel
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Image = { Color = "0 0 0 0.8" }
                }, InitialLayer + $".Item_{itemName}", InitialLayer + $".Item.Changer", InitialLayer + $".Item.Changer");

                elements.Add(new CuiElement()
                {
                    Name = InitialLayer + $".Item.Changer.Input",
                    Parent = InitialLayer + $".Item.Changer",
                    Components =
                    {
                        new CuiInputFieldComponent
                        {
                            Text = itemDef.stackable.ToString(),
                            Color = "1 1 1 1",
                            Align = TextAnchor.MiddleCenter,
                            FontSize = 12,
                            NeedsKeyboard = true,
                            Command = $"jstacks.setstack {itemDef.shortname}",
                            Autofocus = true
                        },
                        new CuiRectTransformComponent {AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0"}
                    }
                });
            }
            else 
            {
                if (!_playersSelectedItems.ContainsKey(player.userID))
                {
                    _playersSelectedItems[player.userID] = new List<string>();
                }

                bool removed = false;

                if (_playersSelectedItems[player.userID].Contains(itemDef.shortname))
                {
                    _playersSelectedItems[player.userID].Remove(itemDef.shortname);
                    removed = true;
                }
                else
                {
                    _playersSelectedItems[player.userID].Add(itemDef.shortname);
                }

                elements.Add(new CuiElement()
                {
                    Name = InitialLayer + ".MultiChoice.InputField.Title",
                    Update = true,
                    Components =
                    {
                        new CuiTextComponent { Text = string.Format(GetMsg("MULTIPLE_CHOICE_INPUT_TITLE", player), _playersSelectedItems[player.userID].Count) },
                    }
                });

                var color = removed ? "0.043725491 0.0554902 0.021568628 0.42" : HexToColor("#708A43", 0.8);

                elements.Add(new CuiElement()
                {
                    Name = InitialLayer + $".Item_{itemDef.shortname}",
                    Update = true,
                    Components =
                    {
                        new CuiImageComponent { Color = color},
                    }
                });
            }

            CuiHelper.AddUi(player, elements);
        }

        private void Notify(BasePlayer player, string message, string color = "green")
        {
            color = color.ToLower();
            var colors = new Dictionary<string, string>()
            {
                ["red"] = "0.7 0.2219512 0.14682925 1",
                ["green"] = "0.4509804 0.5529412 0.27058825 1",
                ["blue"] = "0.1647 0.2941 0.4157 0.8"
            };
            var iconColors = new Dictionary<string, string>()
            {
                ["red"] = "1 0.49271604 0.413 1",
                ["green"] = "0.6164634 0.8113208 0.27171594 1",
                ["blue"] = "0 0.58914757 1 1"
            };
            var textColors = new Dictionary<string, string>()
            {
                ["red"] = "0.97199994 0.8308799 0.80870396 1",
                ["green"] = "0.7348033 0.8490566 0.53266287 1",
                ["blue"] = "0.5030705 0.73362494 0.8962264 1"
            };

            if (!colors.ContainsKey(color)) return;

            int width = (int)(message.Count() * 6 + 22);

            var elements = new CuiElementContainer();

            elements.Add(new CuiElement()
            {
                Parent = InitialLayer + ".Body",
                Name = InitialLayer + ".Toast",
                DestroyUi = InitialLayer + ".Toast",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = $"0 5", OffsetMax = $"{width} 30" },
                    new CuiImageComponent { Color = colors[color], Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat", FadeIn = 0.5f}
                }
            });

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "3 3", OffsetMax = "22 22" },
                Image = { Color = iconColors[color], Sprite = "assets/icons/info.png"}
            }, InitialLayer + ".Toast");

            elements.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "25 3", OffsetMax = "-3 -3" },
                Text = { Text = message, Color = textColors[color], FontSize = 12, Align = TextAnchor.MiddleLeft} 
            }, InitialLayer + ".Toast");
            
            CuiHelper.AddUi(player, elements);

            if (_playersNotifyTimers.ContainsKey(player.userID))
            {
                _playersNotifyTimers[player.userID].Destroy();
                _playersNotifyTimers.Remove(player.userID);
            }

            _playersNotifyTimers[player.userID] = (
                timer.Once(5f, () => 
                {
                    CuiHelper.DestroyUi(player, InitialLayer + ".Toast");
                })
            );
        }

        private void ShowConfirmMenu(BasePlayer player, string message, string commandOnYes)
        {
            var elements = new CuiElementContainer();

            elements.Add(new CuiElement()
            {
                Name = InitialLayer + ".ConfirmBackGround",
                Parent = InitialLayer,
                DestroyUi = InitialLayer + ".ConfirmBackGround",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "1 1" },
                    new CuiImageComponent { Color = "0 0 0 1" }
                }
            });

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-250 -150", OffsetMax = "250 150" },
                Image = { Color = "0.968627453 0.921568632 0.882352948 0.2",  Sprite = "Assets/Content/UI/UI.Background.Tile.psd", ImageType = Image.Type.Tiled }
            }, InitialLayer + ".ConfirmBackGround", InitialLayer + ".Confirm");

            elements.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0.5 0", OffsetMin = "0 -35", OffsetMax = "0 -3" },
                Image = { Color = "0.4509804 0.5529412 0.27058825 1", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat" }
            }, InitialLayer + ".Confirm", InitialLayer + ".Confirm.Button_yes");

            elements.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                Text = { Text = message, Color = "0.968627453 0.921568632 0.882352948 0.6686275", FontSize = 24, Align = TextAnchor.MiddleCenter}
            }, InitialLayer + ".Confirm");

            elements.Add(new CuiButton()
            {
                Button = { Close = InitialLayer + ".ConfirmBackGround", Command = commandOnYes, Color = "0.4509804 0.5529412 0.27058825 1"},
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0.5 0", OffsetMin = "0 -35", OffsetMax = "0 -3" },
                Text = { Text = GetMsg("CONFIRM_TEXT", player) , FontSize = 16, Align = TextAnchor.MiddleCenter}
            }, InitialLayer + ".Confirm");

            elements.Add(new CuiButton()
            {
                Button = { Close = InitialLayer + ".ConfirmBackGround", Color = "0.7 0.2219512 0.14682925 1"},
                RectTransform = { AnchorMin = "0.5 0", AnchorMax = "1 0", OffsetMin = "3 -35", OffsetMax = "0 -3" },
                Text = { Text = GetMsg("DECLINE_TEXT", player), Color = "0.968627453 0.921568632 0.882352948 0.6686275", FontSize = 16, Align = TextAnch
// ... [Code preview truncated due to length. Full source in attached file] ...

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