Building Blocks Not Changing through TC

I change building skin through the setting in TC, then try to apply it, it says that it did but skin does not apply to the building. I tried this with stone. It does reskin to default stone and adobe skin, but does not reskin to brutalist or brick skin. Same thing happens with metal and I assume wood. Video examples attached. 

Sure

using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Newtonsoft.Json;

namespace Oxide.Plugins
{
    [Info("Building Skins", "Marat", "2.0.10")]
    [Description("Automatic application of DLC skins for building blocks")]
    class BuildingSkins : RustPlugin
    {
        [PluginReference] private Plugin ImageLibrary;

        #region Field

        private const string InitialLayer = "UI_BuildingLayer";
        private const string CupboardLayer = "UI_CupboardLayer";

        private const string permissionUse = "buildingskins.use";
        private const string permissionAll = "buildingskins.all";
        private const string permissionBuild = "buildingskins.build";
        private const string permissionTc = "buildingskins.tc";
        private const string permissionAdmin = "buildingskins.admin";

        private readonly Dictionary<ulong, Coroutine> runningCoroutines = new();
        private readonly Dictionary<BuildingGrade.Enum, List<ulong>> gradesSkin = new();

        private readonly Dictionary<uint, string> colors = new()
        {
            [1] = "0.38 0.56 0.74 1.0",
            [2] = "0.45 0.71 0.34 1.0",
            [3] = "0.57 0.29 0.83 1.0",
            [4] = "0.42 0.17 0.11 1.0",
            [5] = "0.82 0.46 0.13 1.0",
            [6] = "0.87 0.87 0.87 1.0",
            [7] = "0.20 0.20 0.18 1.0",
            [8] = "0.40 0.33 0.27 1.0",
            [9] = "0.20 0.22 0.34 1.0",
            [10] = "0.24 0.35 0.20 1.0",
            [11] = "0.73 0.30 0.18 1.0",
            [12] = "0.78 0.53 0.39 1.0",
            [13] = "0.84 0.66 0.22 1.0",
            [14] = "0.34 0.33 0.31 1.0",
            [15] = "0.21 0.34 0.37 1.0",
            [16] = "0.66 0.61 0.56 1.0"
        };

        #endregion

        #region Oxide Hooks

        private void OnServerInitialized()
        {
            if (ImageLibrary == null)
            {
                PrintError("[ImageLibrary] not found! Plugin is disabled!");
                Interface.Oxide.UnloadPlugin(Title);
                return;
            }

            LoadData();
            AddCovalenceCommand(config.Commands, nameof(CmdChangeSkin));
            permission.RegisterPermission(permissionUse, this);
            permission.RegisterPermission(permissionAll, this);
            permission.RegisterPermission(permissionBuild, this);
            permission.RegisterPermission(permissionTc, this);
            permission.RegisterPermission(permissionAdmin, this);

            foreach (var list in config.BuildingImages)
            {
                var skinId = list.Value.Select(x => x.SkinId).ToList();
                gradesSkin.Add((BuildingGrade.Enum)(list.Key + 1), skinId);

                foreach (var info in list.Value.Where(x => !string.IsNullOrEmpty(x.Url)))
                {
                    ImageLibrary.Call("AddImage", info.Url, info.Title);
                    if (config.SeparatePermissions && info.SkinId != 0 && !string.IsNullOrEmpty(info.Title))
                    {
                        if (!permission.PermissionExists(info.Title))
                        {
                            permission.RegisterPermission($"buildingskins.{info.Title}".ToLower(), this);
                        }
                    }
                }
            }

            for (int i = 0; i < BasePlayer.activePlayerList.Count; i++)
            {
                OnPlayerConnected(BasePlayer.activePlayerList[i]);
            }
        }

        private void Unload()
        {
            for (int i = 0; i < BasePlayer.activePlayerList.Count; i++)
            {
                var player = BasePlayer.activePlayerList[i];
                CuiHelper.DestroyUi(player, InitialLayer);
                CuiHelper.DestroyUi(player, CupboardLayer);
                StopCoroutine(player);
            }
            SaveData();
            runningCoroutines.Clear();
            config = null;
        }

        private void OnServerSave() => SaveData();

        private void OnPlayerConnected(BasePlayer player)
        {
            if (player == null || !player.IsConnected) return;
            if (player.IsReceivingSnapshot)
            {
                timer.Once(1f, () => OnPlayerConnected(player));
                return;
            }
            StartCoroutine(player, PreloadImages(player));
            if (!storedData.PlayerData.TryGetValue(player.userID.Get(), out var data))
            {
                data = new Data
                {
                    ChangeHammer = true,
                    NeedsRepair = true,
                    EnableAnimation = true,
                    RandomColor = false,
                    Color = 9
                };
                storedData.PlayerData[player.userID] = data;
            }
            player.SetInfo("client.SelectedShippingContainerBlockColour", data.RandomColor ? data.Color.ToString() : player.GetInfoString("client.SelectedShippingContainerBlockColour", "0"));
        }

        private void OnPlayerDisconnected(BasePlayer player) => StopCoroutine(player);

        private void OnPlayerRespawned(BasePlayer player)
        {
            if (player == null || !player.IsConnected) return;
            var data = storedData.PlayerData.TryGetValue(player.userID, out var playerData) ? playerData : null;
            if(data == null)
                player.SetInfo("client.SelectedShippingContainerBlockColour", player.GetInfoString("client.SelectedShippingContainerBlockColour", "0"));
            else
                player.SetInfo("client.SelectedShippingContainerBlockColour", data.RandomColor ? data.Color.ToString() : player.GetInfoString("client.SelectedShippingContainerBlockColour", "0"));
        }

        private void OnHammerHit(BasePlayer player, HitInfo info)
        {
            if (player == null || info == null || info.HitEntity == null) return;
            if (!permission.UserHasPermission(player.UserIDString, permissionUse)) return;
            var block = info.HitEntity as BuildingBlock;
            if (block == null || !gradesSkin.TryGetValue(block.grade, out var skinId) || skinId == null) return;
            var skinID = GetPlayerSkinID(player, block.grade);
            var playerData = storedData.PlayerData[player.userID];
            if (block.SecondsSinceAttacked <= 30f) return;
            if (block.skinID != 0 && block.grade.ToString() == "Metal" && !playerData.RandomColor) block.SetCustomColour((uint)player.GetInfoInt("client.SelectedShippingContainerBlockColour", 0));
            if (block.skinID == skinID) return;
            if ((config.BuildingBlocked && !player.CanBuild() || block.OwnerID != player.userID) && !permission.UserHasPermission(player.UserIDString, permissionAdmin)) return;
            if (!playerData.ChangeHammer || block.health != block.MaxHealth() && !playerData.NeedsRepair) return;
            block.skinID = skinID;
            block.ChangeGradeAndSkin(block.grade, skinID, true, true);
            if (playerData.EnableAnimation) block.ClientRPC(null, "DoUpgradeEffect", (int)block.grade, skinID);
        }

        private object OnStructureUpgrade(BuildingBlock block, BasePlayer player, BuildingGrade.Enum grade, ulong skin)
        {
            if (player == null || block == null) return null;
            if (!permission.UserHasPermission(player.UserIDString, permissionUse)) return null;
            if (skin != 0 && player.blueprints.steamInventory.HasItem((int)skin)) return null;
            if (!gradesSkin.TryGetValue(grade, out var skinId) || skinId == null) return null;
            var skinID = GetPlayerSkinID(player, grade);
            var playerData = storedData.PlayerData[player.userID];
            if (block.SecondsSinceAttacked <= 30f)
            {
                block.OnRepairFailed(player, string.Format("Unable to repair: Recently damaged. Repairable in: {0:N0}s.", 30f - block.SecondsSinceAttacked));
                return false;
            }
            if (block.skinID != 0 && grade.ToString() == "Metal" && !playerData.RandomColor) block.SetCustomColour((uint)player.GetInfoInt("client.SelectedShippingContainerBlockColour", 0));
            if (block.skinID == skinID && block.grade == grade) return false;
            NextTick(() =>
            {
                if (block == null || block.IsDestroyed) return;
                block.skinID = skinID;
                block.ChangeGradeAndSkin(block.grade, skinID, true, true);
                if (playerData.EnableAnimation) block.ClientRPC(null, "DoUpgradeEffect", (int)block.grade, skinID);
                ///for plugin BuildingGrades
                if (block.skinID != 0 && grade.ToString() == "Metal" && !playerData.RandomColor) block.SetCustomColour((uint)player.GetInfoInt("client.SelectedShippingContainerBlockColour", 0));
            });
            return null;
        }

        ///for plugin BuildingGrades
        private void OnStructureGradeUpdated(BuildingBlock block, BasePlayer player, BuildingGrade.Enum oldGrade, BuildingGrade.Enum newGrade)
        {
            OnStructureUpgrade(block, player, newGrade, block.skinID);
        }

        private void OnLootEntity(BasePlayer player, BaseEntity entity)
        {
            if (player == null || entity == null) return;
            var cupboard = entity.gameObject.GetComponent<BuildingPrivlidge>();
            if (cupboard == null || !permission.UserHasPermission(player.UserIDString, permissionTc)) return;
            if (config.ChangeSkinTC && cupboard.OwnerID != player.userID) return;
            TCupboardLayer(player);
        }

        private void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity)
        {
            if (player == null || entity == null) return;
            if (entity is BuildingPrivlidge)
            {
                CuiHelper.DestroyUi(player, CupboardLayer);
            }
        }

        #endregion

        #region Configuration

        private static PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Building skin change commands")] public string[] Commands;
            [JsonProperty("Block building skin in building blocked")] public bool BuildingBlocked;
            [JsonProperty("Changing skin from tool cupboard only by owner")] public bool ChangeSkinTC;
            [JsonProperty("Number of blocks updated per tick")] public int UpdatesPerTick;
            [JsonProperty("Use separate permissions for skins")] public bool SeparatePermissions;
            [JsonProperty("Image and description settings")] public Dictionary<int, List<BlockInfo>> BuildingImages;
            public Oxide.Core.VersionNumber Version;
        }

        protected override void LoadDefaultConfig()
        {
            config = new PluginConfig
            {
                Commands = new string[] { "bskin", "building.skin" },
                BuildingBlocked = true,
                ChangeSkinTC = true,
                UpdatesPerTick = 5,
                SeparatePermissions = false,
                BuildingImages = new Dictionary<int, List<BlockInfo>>
                {
                    [0] = new List<BlockInfo>
                    {
                        new("Wood", "https://i.ibb.co/yqsWpbp/wood.png", 0),
                        new("Frontier", "https://i.ibb.co/b2bZFXj/frontier.png", 10232),
                        new("Gingerbread", "https://i.ibb.co/Tw67yBM/gingerbread.png", 2)
                    },
                    [1] = new List<BlockInfo>
                    {
                        new("Stone", "https://i.ibb.co/jw9FJFP/stone.png", 0),
                        new("Adobe", "https://i.ibb.co/Ky1MBJ7/adobe.png", 10220),
                        new("Brick", "https://i.ibb.co/vjqh3Hj/brick.png", 10223),
                        new("Brutalist", "https://i.ibb.co/86bpvS2/brutalist.png", 10225)
                    },
                    [2] = new List<BlockInfo>
                    {
                        new("Metal", "https://i.ibb.co/M9RPSZ2/metal.png", 0),
                        new("Container", "https://i.ibb.co/YWzfwS4/container.png", 10221)
                    },
                    [3] = new List<BlockInfo>
                    {
                        new("TopTier", "https://i.ibb.co/T0Nwfvp/toptire.png", 0)
                    }
                },
                Version = Version
            };
        }

        private class BlockInfo
        {
            public string Title;
            public string Url;
            public ulong SkinId;

            public BlockInfo(string title, string url, ulong skinId)
            {
                Title = title;
                Url = url;
                SkinId = skinId;
            }
        }

        protected override void SaveConfig() => Config.WriteObject(config);
        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) LoadDefaultConfig();
                if (config.Version < Version)
                {
                    PrintWarning("Config update detected! Updating config values...");
                    if (config.Version < new Core.VersionNumber(2, 0, 0))
                    {
                        LoadDefaultConfig();
                    }
                    if (config.Version < new Core.VersionNumber(2, 0, 3))
                    {
                        if (config.BuildingImages[0][3].SkinId == 10225)
                        {
                            config.BuildingImages[0][3].SkinId = 3;
                        }
                    }
                    if (config.Version < new Core.VersionNumber(2, 0, 4))
                    {
                        config.ChangeSkinTC = true;
                    }
                    config.Version = Version;
                    PrintWarning("Config update completed!");
                }
            }
            catch
            {
                PrintWarning("The config file contains an error and has been replaced with the default config.");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        #endregion

        #region Commands

        [ConsoleCommand("UI_BuildingController")]
        private void CmdConsoleHandler(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !arg.HasArgs(1)) return;
            var playerData = storedData.PlayerData[player.userID];
            SoundEffect(player, "assets/bundled/prefabs/fx/notice/loot.drag.grab.fx.prefab");

            int index, skinIndex;
            switch (arg.Args[0].ToLower())
            {
                case "open":
                    {
                        InitializeLayers(player, true);
                        break;
                    }
                case "build":
                    {
                        var blocks = player.GetBuildingPrivilege().GetBuilding()?.buildingBlocks.ToArray();
                        if (blocks == null) return;
                        PrintToChat(player, GetMessage("Lang_UpdateBuilding", player));
                        StartCoroutine(player, UpgradeSkin(player, blocks));
                        TCupboardLayer(player);
                        SoundEffect(player, "assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab");
                        break;
                    }
                case "change":
                    {
                        if (!int.TryParse(arg.Args[1], out index) || !int.TryParse(arg.Args[2], out skinIndex)) return;
                        ImageLayers(player, index, skinIndex);
                        break;
                    }
                case "choose":
                    {
                        if (!int.TryParse(arg.Args[1], out index) || !int.TryParse(arg.Args[2], out skinIndex)) return;
                        var grades = gradesSkin.ElementAt(index);
                        playerData.GetType().GetField(grades.Key.ToString())?.SetValue(playerData, grades.Value[skinIndex]);
                        ImageLayers(player, index, skinIndex);
                        SoundEffect(player, "assets/prefabs/missions/effects/mission_objective_complete.prefab");
                        break;
                    }
                case "settings":
                    {
                        SettingsLayer(player);
                        break;
                    }
                case "colors":
                    {
                        if (!int.TryParse(arg.Args[1], out index)) return;
                        ColorLayer(player, index);
                        break;
                    }
                case "setcolor":
                    {
                        if (!int.TryParse(arg.Args[1], out index) || !uint.TryParse(arg.Args[2], out uint colorId)) return;
                        player.SetInfo("client.SelectedShippingContainerBlockColour", colorId.ToString());
                        playerData.Color = colorId;
                        ColorLayer(player, index);
                        SoundEffect(player, "assets/prefabs/deployable/repair bench/effects/skinchange_spraypaint.prefab");
                        break;
                    }
                case "randomcolor":
                    {
                        if (!int.TryParse(arg.Args[1], out index)) return;
                        var randomColor = !playerData.RandomColor;
                        playerData.RandomColor = randomColor;
                        player.SetInfo("client.SelectedShippingContainerBlockColour", randomColor ? "0" : playerData.Color.ToString());
                        ColorLayer(player, index);
                        break;
                    }
                case "hammer":
                    {
                        var changeHammer = !playerData.ChangeHammer;
                        playerData.ChangeHammer = changeHammer;
                        SettingsLayer(player);
                        break;
                    }
                case "repair":
                    {
                        var needsRepair = !playerData.NeedsRepair;
                        playerData.NeedsRepair = needsRepair;
                        SettingsLayer(player);
                        break;
                    }
                case "animation":
                    {
                        var enableAnimation = !playerData.EnableAnimation;
                        playerData.EnableAnimation = enableAnimation;
                        SettingsLayer(player);
                        break;
                    }
            }
        }

        private void CmdChangeSkin(IPlayer ipPlayer, string command, string[] arg)
        {
            var player = ipPlayer?.Object as BasePlayer;
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, permissionUse))
            {
                PrintToChat(player, GetMessage("Lang_NoPermissions", player));
                return;
            }
            if (arg.Length == 0)
            {
                InitializeLayers(player, true);
                return;
            }
            if (runningCoroutines.ContainsKey(player.userID))
            {
                PrintToChat(player, GetMessage("Lang_UpdateProgress", player));
                return;
            }
            if (arg.Length > 0 && config.BuildingBlocked && !player.CanBuild() && !permission.UserHasPermission(player.UserIDString, permissionAdmin))
            {
                PrintToChat(player, GetMessage("Lang_BuildingBlocked", player));
                return;
            }
            switch (arg[0].ToLower())
            {
                case "build":
                    {
                        if (!permission.UserHasPermission(player.UserIDString, permissionBuild))
                        {
                            PrintToChat(player, GetMessage("Lang_NoPermissions", player));
                            return;
                        }
                        var entity = GetLookEntity(player);
                        if (entity == null)
                        {
                            PrintToChat(player, GetMessage("Lang_NotFoundBuilding", player));
                            return;
                        }
                        if (entity.OwnerID != player.userID && !permission.UserHasPermission(player.UserIDString, permissionAdmin))
                        {
                            PrintToChat(player, GetMessage("Lang_NotOwnerBuilding", player));
                            return;
                        }
                        var blocks = entity.GetBuilding()?.buildingBlocks.ToArray();
                        if (blocks == null) return;
                        PrintToChat(player, GetMessage("Lang_UpdateBuilding", player));
                        StartCoroutine(player, UpgradeSkin(player, blocks));
                        break;
                    }
                case "all":
                    {
                        if (!permission.UserHasPermission(player.UserIDString, permissionAll))
                        {
                            PrintToChat(player, GetMessage("Lang_NoPermissions", player));
                            return;
                        }
                        if (arg.Length > 1 && !ulong.TryParse(arg[1], out var owner))
                        {
                            PrintToChat(player, GetMessage("Lang_NotFoundPlayer", player));
                            return;
                        }
                        var targetOwner = arg.Length > 1 ? ulong.Parse(arg[1]) : player.userID.Get();
                        if (!permission.UserHasPermission(player.UserIDString, permissionAdmin) && targetOwner != player.userID)
                        {
                            PrintToChat(player, GetMessage("Lang_NoPermissions", player));
                            return;
                        }
                        var blockOwner = BaseNetworkable.serverEntities.OfType<BuildingBlock>().Where(x => x.OwnerID == targetOwner).ToArray();
                        if (blockOwner.Length == 0)
                        {
                            PrintToChat(player, GetMessage("Lang_NotFoundBlocks", player));
                            return;
                        }
                        PrintToChat(player, GetMessage(targetOwner != player.userID.Get() ? "Lang_UpdateAllTarget" : "Lang_UpdateAll", player));
                        StartCoroutine(player, UpgradeSkin(player, blockOwner));
                        break;
                    }
            }
        }

        #endregion

        #region Methods

        private void StartCoroutine(BasePlayer player, IEnumerator routine)
        {
            if (runningCoroutines.ContainsKey(player.userID.Get())) return;
            var coroutine = ServerMgr.Instance?.StartCoroutine(routine);
            if (coroutine != null) runningCoroutines[player.userID.Get()] = coroutine;
        }

        private void StopCoroutine(BasePlayer player)
        {
            if (!runningCoroutines.ContainsKey(player.userID.Get())) return;
            var coroutine = runningCoroutines[player.userID.Get()];
            if (coroutine != null) ServerMgr.Instance?.StopCoroutine(coroutine);
            runningCoroutines.Remove(player.userID.Get());
            var entity = player?.inventory?.loot?.entitySource;
            if (entity == null || !permission.UserHasPermission(player.UserIDString, permissionTc)) return;
            if (entity is BuildingPrivlidge)
            {
                if (config.ChangeSkinTC && entity.OwnerID != player.userID.Get()) return;
                TCupboardLayer(player);
            }
        }

       private IEnumerator UpgradeSkin(BasePlayer player, BuildingBlock[] blocks)
        {
            var count = 0;
            for (int i = 0; i < blocks.Length; i++)
            {
                var block = blocks[i];
                if (block == null || block.IsDestroyed) continue;
                if (!gradesSkin.TryGetValue(block.grade, out var skinId) || skinId == null) continue;
                var skinID = GetPlayerSkinID(player, block.grade);
                var playerData = storedData.PlayerData[player.userID.Get()];
                // disabled because it hinders the plugin functionality and doesnt really serve a reasonable purpose
                //if (skinID != 0 && player.blueprints.steamInventory.HasItem((int)skinID)) continue;
                if (block.SecondsSinceAttacked < 30f) continue;
                if (block.skinID != 0 && block.grade.ToString() == "Metal" && !playerData.RandomColor) block.SetCustomColour((uint)player.GetInfoInt("client.SelectedShippingContainerBlockColour", 0));
                if (block.skinID == skinID) continue;
                block.skinID = skinID;
                block.ChangeGradeAndSkin(block.grade, skinID, true, true);
                count++;

                if (i % config.UpdatesPerTick == 0)
                    yield return CoroutineEx.waitForFixedUpdate;
            }

            if (count == 0)
                PrintToChat(player, GetMessage("Lang_UpdateNotRequired", player));
            else
                // added string.Format to fix FormatException error when updating all skins
                PrintToChat(player, string.Format(GetMessage("Lang_UpdateCompleted", player), count, blocks.Length));

            StopCoroutine(player);
        }

        private bool HasPermission(BasePlayer player, string name)
        {
            foreach (var blockInfoList in config.BuildingImages.Values)
            {
                foreach (var blockInfo in blockInfoList)
                {
                    if (blockInfo.Title == name && permission.UserHasPermission(player.UserIDString, $"buildingskins.{blockInfo.Title}".ToLower()))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private ulong GetPlayerSkinID(BasePlayer player, BuildingGrade.Enum grade)
        {
            var playerData = storedData.PlayerData.TryGetValue(player.userID.Get(), out var data) ? data : null;
            return (ulong)(playerData?.GetType().GetField(grade.ToString()).GetValue(playerData) ?? 0);
        }

        private BuildingBlock GetLookEntity(BasePlayer player)
        {
            return Physics.Raycast(player.eyes.HeadRay(), out RaycastHit raycastHit, 4f, Rust.Layers.Mask.Construction) ? raycastHit.GetEntity() as BuildingBlock : null;
        }

        private static void SoundEffect(BasePlayer player, string effect = null)
        {
            EffectNetwork.Send(new Effect(effect, player, 0, new Vector3(), new Vector3()), player.Connection);
        }

        private string GetMessage(string key, BasePlayer player)
        {
            return lang.GetMessage(key, this, player.UserIDString);
        }

        #endregion

        #region Interfaces

        private void InitializeLayers(BasePlayer player, bool update)
        {
            float fade = !update ? 0f : 0.25f;
            CuiElementContainer container = new CuiElementContainer();

            container.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.235 0.227 0.2 0.9" },
                    new CuiNeedsCursorComponent()
                }
            });

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                Button = { Close = InitialLayer, Color = "0.141 0.137 0.096 0.98", Sprite = "assets/content/ui/ui.background.transparent.radial.psd" }
            }, InitialLayer);

            container.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"-250 -320", OffsetMax = $"250 300" },
                Image = { Color = "0.117 0.121 0.109 0.8", Material = "assets/content/ui/uibackgroundblur.mat", FadeIn = fade }
            }, InitialLayer, InitialLayer + ".Main");

            container.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 1", AnchorMax = "1 1", OffsetMin = "30 -60", OffsetMax = "-30 -2" },
                Text = { Text = GetMessage("Lang_InterfaceTitle", player).ToUpper(), Color = "0.78 0.74 0.70 1.0", FontSize = 20, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter, FadeIn = fade }
            }, InitialLayer + ".Main");

            container.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 0", OffsetMin = "0 5", OffsetMax = "0 25" },
                Text = { Text = $"• {GetMessage("Lang_InterfaceDescr", player)}".ToUpper(), Color = "0.78 0.74 0.70 0.6", FontSize = 12, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter, FadeIn = fade }
            }, InitialLayer + ".Main");

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-25 -25", OffsetMax = "-5 -5" },
                Button = { Close = InitialLayer, Color = "0.71 0.22 0.15 1.0", Sprite = "assets/icons/close.png" }
            }, InitialLayer + ".Main");

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "5 -25", OffsetMax = "25 -5" },
                Button = { Command = $"UI_BuildingController settings", Color = "0.31 0.64 0.89 0.5", Sprite = "assets/icons/gear.png" }
            }, InitialLayer + ".Main", InitialLayer + ".Settings");

            CuiHelper.AddUi(player, container);

            for (var i = 0; i < config.BuildingImages.Count; i++)
            {
                var grades = gradesSkin.ElementAt(i);
                var skinID = GetPlayerSkinID(player, grades.Key);
                var skinIndex = grades.Value.IndexOf(skinID);
                ImageLayers(player, i, skinIndex);
            }
        }

        private void ImageLayers(BasePlayer player, int index, int skinIndex)
        {
            var playerData = storedData.PlayerData[player.userID.Get()];
            var listIndex = config.BuildingImages[index];
            var nextIndex = (skinIndex + 1) % listIndex.Count;
            var grades = gradesSkin.ElementAt(index);
            var skinID = GetPlayerSkinID(player, grades.Key);
            var selected = listIndex[skinIndex].SkinId == skinID;
            var hasSkin = listIndex.Any(x => !string.IsNullOrEmpty(x.Url) && x.SkinId != 0);
            var hasPermission = HasPermission(player, listIndex[skinIndex].Title);
            var isBlocked = config.SeparatePermissions && !hasPermission && skinIndex != 0;

            if (isBlocked && selected)
            {
                playerData.GetType().GetField(grades.Key.ToString())?.SetValue(playerData, grades.Value[0]);
                ImageLayers(player, index, 0);
                return;
            }

            const int marginTop = 10, margin = 6, width = 200, height = 250;
            var offsetX = (index % 2 == 0 ? -1 : 1) * ((width + margin) / 2 + margin);
            var offsetY = (index < 2 ? 1 : -1) * ((height + margin) / 2 + margin) - marginTop;

            CuiElementContainer container = new CuiElementContainer();

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{offsetX - width / 2} {offsetY - height / 2}", OffsetMax = $"{offsetX + width / 2} {offsetY + height / 2}" },
                Button = { Command = hasSkin ? $"UI_BuildingController change {index} {nextIndex}" : "", Color = "0.22 0.25 0.16 0.9", Material = "assets/content/ui/uibackgroundblur.mat" },
            }, InitialLayer + ".Main", InitialLayer + $".Button.{index}");

            container.Add(new CuiElement()
            {
                Parent = InitialLayer + $".Button.{index}",
                Name = InitialLayer + $".Image.{index}",
                DestroyUi = InitialLayer + $".Image.{index}",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-85 -72", OffsetMax = "85 98" },
                    new CuiRawImageComponent { Png = (string) ImageLibrary.Call("GetImage", listIndex[skinIndex].Title), Color = hasSkin && !isBlocked ? "1 1 1 1" : "0.8 0.8 0.8 0.5" }
                }
            });

            if (hasSkin)
            {
                container.Add(new CuiPanel()
                {
                    RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-28 -28", OffsetMax = "-5 -5" },
                    Image = { Color = "0.81 0.77 0.74 0.8", Sprite = "assets/icons/refresh.png" }
                }, InitialLayer + $".Button.{index}");
            }
            if (!hasSkin || isBlocked)
            {
                container.Add(new CuiPanel()
                {
                    RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-22 -30", OffsetMax = "22 30" },
                    Image = { Color = "0.81 0.77 0.74 0.8", Sprite = "assets/content/ui/[email protected]" }
                }, InitialLayer + $".Image.{index}");
            }

            if (grades.Key.ToString() == "Metal" && !isBlocked)
            {
                if (skinIndex != 0)
                {
                    var colorIcon = colors.TryGetValue((uint)player.GetInfoInt("client.SelectedShippingContainerBlockColour", 0), out var value) ? value : "0.20 0.30 0.40 1.0";

                    container.Add(new CuiButton()
                    {
                        RectTransform = { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "5 -28", OffsetMax = "28 -5" },
                        Button = { Command = $"UI_BuildingController colors {index}", Color = colorIcon, Sprite = "assets/icons/circle_closed.png" }
                    }, InitialLayer + $".Button.{index}", InitialLayer + ".Color");

                    container.Add(new CuiPanel()
                    {
                        RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "-2 -2", OffsetMax = "2 2" },
                        Image = { Color = "0.81 0.77 0.74 1.0", Sprite = "assets/icons/workshop.png" }
                    }, InitialLayer + ".Color");
                }
                else CuiHelper.DestroyUi(player, InitialLayer + ".Color");
            }

            container.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 0", OffsetMin = "0 0", OffsetMax = "0 26" },
                Image = { Color = "0 0 0 0.5" }
            }, InitialLayer + $".Button.{index}", InitialLayer + $".Title.{index}");

            container.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "10 0", OffsetMax = "125 26" },
                Text = { Text = GetMessage(listIndex[skinIndex].Title, player).ToUpper(), Color = "0.81 0.77 0.74 1.0", FontSize = 11, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleLeft }
            }, InitialLayer + $".Title.{index}");

            var textTitle = GetMessage(selected ? "Lang_SkinInstalled" : (isBlocked ? "Lang_Unavailable" : "Lang_InterfaceApply"), player);
            var colorTitle = selected ? "0.59 0.84 0.18 1.0" : isBlocked ? "0.81 0.77 0.74 1.0" : "0.30 0.65 0.90 1.0";
            var colorButton = selected ? "0.30 0.36 0.16 1.0" : isBlocked ? "0.34 0.33 0.31 1.0" : "0.20 0.30 0.40 1.0";

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-75 0", OffsetMax = "0 26" },
                Button = { Command = hasSkin && !isBlocked && !selected ? $"UI_BuildingController choose {index} {skinIndex}" : "", Color = colorButton, Material = "assets/content/ui/uibackgroundblur.mat" },
                Text = { Text = textTitle.ToUpper(), Color = colorTitle, FontSize = 11, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter }
            }, InitialLayer + $".Title.{index}");

            CuiHelper.AddUi(player, container);
        }

        private void SettingsLayer(BasePlayer player)
        {
            CuiElementContainer container = new CuiElementContainer();

            container.Add(new CuiElement()
            {
                Parent = InitialLayer + ".Settings",
                Name = InitialLayer + ".SettingsMenu",
                DestroyUi = InitialLayer + ".SettingsMenu",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "-350 -5", OffsetMax = "5 5" },
                    new CuiImageComponent { Color = "0.20 0.30 0.40 1.0", Material = "assets/content/ui/uibackgroundblur.mat" }
                }
            });

            container.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "10 0", OffsetMax = "0 0" },
                Text = { Text = GetMessage("Lang_MenuSettings", player).ToUpper(), Color = "0.78 0.74 0.70 1.0", FontSize = 20, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleLeft }
            }, InitialLayer + ".SettingsMenu");

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-25 -25", OffsetMax = "-5 -5" },
                Button = { Close = InitialLayer + ".SettingsMenu", Color = "0.71 0.22 0.15 1.0", Sprite = "assets/icons/close.png" }
            }, InitialLayer + ".SettingsMenu");

            container.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 0", OffsetMin = "2 -150", OffsetMax = "-35 0" },
                Image = { Color = "0.117 0.121 0.109 0.8", Material = "assets/content/ui/uibackgroundblur.mat" }
            }, InitialLayer + ".SettingsMenu", InitialLayer + ".SettingsButton");

            string[] langKeys = { "Lang_ChangeHammer", "Lang_NeedsRepair", "Lang_EnableAnimation" };
            string[] commands = { "UI_BuildingController hammer", "UI_BuildingController repair", "UI_BuildingController animation" };
            var playerData = storedData.PlayerData[player.userID.Get()];
            var margin = 0;

            for (var i = 0; i < 3; i++)
            {
                var active = new[] { playerData.ChangeHammer, playerData.ChangeHammer && playerData.NeedsRepair, playerData.EnableAnimation }[i];
                var text = GetMessage($"Lang_Setting{(active ? "Enable" : "Disable")}", player);
                var textlang = GetMessage(langKeys[i], player);

                container.Add(new CuiButton()
                {
                    RectTransform = { AnchorMin = "0 1", AnchorMax = "1 1", OffsetMin = $"10 {-50 - margin}", OffsetMax = $"-10 {-15 - margin}" },
                    Button = { Command = commands[i], Color = "0.34 0.33 0.31 1.0", Material = "assets/content/ui/uibackgroundblur.mat" },
                }, InitialLayer + ".SettingsButton", InitialLayer + $".SettingsButton.{i}");

                container.Add(new CuiPanel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "0 0", OffsetMax = "50 0" },
                    Image = { Color = active ? "0.36 0.44 0.22 1.0" : "0.71 0.22 0.15 1.0", Material = "assets/content/ui/uibackgroundblur.mat" },
                }, InitialLayer + $".SettingsButton.{i}", InitialLayer + $".TextButton");

                container.Add(new CuiLabel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Text = { Text = text.ToUpper(), Color = active ? "0.78 0.74 0.70 1.0" : "0.78 0.74 0.70 0.6", FontSize = 16, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter }
                }, InitialLayer + $".TextButton");

                container.Add(new CuiLabel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "60 0", OffsetMax = "-5 0" },
                    Text = { Text = textlang.ToUpper(), Color = "0.78 0.74 0.70 1.0", FontSize = 12, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleLeft }
                }, InitialLayer + $".SettingsButton.{i}");

                margin += 45;
            }

            CuiHelper.AddUi(player, container);
        }

        private void ColorLayer(BasePlayer player, int index)
        {
            var playerData = storedData.PlayerData[player.userID.Get()];
            var playerColor = (uint)player.GetInfoInt("client.SelectedShippingContainerBlockColour", 0);
            CuiElementContainer container = new CuiElementContainer();

            container.Add(new CuiElement()
            {
                Parent = InitialLayer + ".Color",
                Name = InitialLayer + ".SetColor",
                DestroyUi = InitialLayer + ".SetColor",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "-250 -5", OffsetMax = "5 5" },
                    new CuiImageComponent { Color = colors.TryGetValue(playerColor, out var value) ? value : "0.20 0.30 0.40 1.0", Material = "assets/content/ui/uibackgroundblur.mat" }
                }
            });

            container.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "10 0", OffsetMax = "0 0" },
                Text = { Text = GetMessage("Lang_ColorSettings", player).ToUpper(), Color = "0.78 0.74 0.70 1.0", FontSize = 20, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleLeft }
            }, InitialLayer + ".SetColor");

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-25 -25", OffsetMax = "-5 -5" },
                Button = { Close = InitialLayer + ".SetColor", Color = "0.71 0.22 0.15 1.0", Sprite = "assets/icons/close.png" }
            }, InitialLayer + ".SetColor");

            container.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 0", OffsetMin = $"2 {(playerData.RandomColor ? -42 : -228)}", OffsetMax = "-80 0" },
                Image = { Color = "0.117 0.121 0.109 0.8", Material = "assets/content/ui/uibackgroundblur.mat" }
            }, InitialLayer + ".SetColor", InitialLayer + ".ColorButton");

            container.Add(new CuiButton()
            {
                RectTransform = { AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-89 -35", OffsetMax = "89 -6" },
                Button = { Command = $"UI_BuildingController randomcolor {index}", Color = "0.34 0.33 0.31 1.0", Material = "assets/content/ui/uibackgroundblur.mat" }
            }, InitialLayer + ".ColorButton", InitialLayer + ".RandomButton");

            container.Add(new CuiLabel()
            {
                RectTransform = { AnchorMin = "0.25 0", AnchorMax = "0.9 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                Text = { Text = GetMessage("Lang_Randomcolor", player).ToUpper(), Color = "0.78 0.74 0.70 1.0", FontSize = 12, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter }
            }, InitialLayer + ".RandomButton");

            var sprite = playerData.RandomColor ? "assets/icons/circle_closed.png" : "assets/icons/circle_open.png";

            container.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "23 5", OffsetMax = "42 -5" },
                Image = { Color = "0.85 0.85 0.85 0.8", Sprite = sprite }
            }, InitialLayer + ".RandomButton", InitialLayer + ".Panel");

            if (playerData.RandomColor)
            {
                container.Add(new CuiPanel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "3 3", OffsetMax = "-3 -3" },
                    Image = { Color = "0 0 0 1", Sprite = "assets/icons/check.png" }
                }, InitialLayer + ".Panel");
            }
            else
            {
                const int marginTop = 2, margin = 6, width = 40, height = 40;

                for (var i = 0; i < colors.Count; i++)
                {
                    var colorIndex = colors.ElementAt(i).Key;
                    var colorValue = colors.ElementAt(i).Value;
                    var offsetX = i % 4 * (width + margin) - (2 * width + 1.5 * margin);
                    var offsetY = -i / 4 * (height + margin) + 35 - marginTop;

                    container.Add(new CuiButton
                    {
                        RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{offsetX} {offsetY}", OffsetMax = $"{offsetX + width} {offsetY + height}" },
                        Button = { Command = colorIndex != playerColor ? $"UI_BuildingController setcolor {index} {colorIndex}" : "", Color = colorValue, Material = "assets/content/ui/uibackgroundblur.mat" }
                    }, InitialLayer + ".ColorButton", InitialLayer + ".PanelButton");

                    if (colorIndex == playerColor)
                    {
                        container.Add(new CuiPanel()
                        {
                            RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "2 2", OffsetMax = "-2 -2" },
                            Image = { Color = "0.59 0.84 0.18 1.0", Sprite = "assets/icons/vote_up.png" }
                        }, InitialLayer + ".PanelButton");
                    }
                }
            }

            CuiHelper.AddUi(player, container);
        }

        private void TCupboardLayer(BasePlayer player)
        {
            var isRunning = runningCoroutines.ContainsKey(player.userID.Get());
            CuiElementContainer container = new CuiElementContainer();

            container.Add(new CuiElement()
            {
                Parent = "Overlay",
                Name = CupboardLayer,
                DestroyUi = CupboardLayer,
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0.5 0.0", AnchorMax = "0.5 0.0", OffsetMin = "420 595", OffsetMax = "572 616" },
                    new CuiImageComponent { Color = isRunning ? "0.90 0.53 0.05 1.0" : "0.40 0.50 0.20 1.0", Material = "assets/content/ui/uibackgroundblur.mat" }
                }
            });

            var text = GetMessage(isRunning ? "Lang_TcWait" : "Lang_TcChangeSkin", player);
            var color = isRunning ? "1 1 1 1" : "0.70 0.90 0.45 1.0";
            var sprite = isRunning ? "assets/icons/refresh.png" : "assets/icons/brush.png";

            container.Add(new CuiButton
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "22 0", OffsetMax = "0 0" },
                Button = { Command = !isRunning ? "UI_BuildingController build" : "", Color = "0 0 0 0" },
                Text = { Text = text.ToUpper(), Color = color, FontSize = 11, Align = TextAnchor.MiddleCenter }
            }, CupboardLayer, CupboardLayer + ".Button");

            container.Add(new CuiPanel()
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "4 2", OffsetMax = "22 -2" },
                Image = { Color = "1 1 1 1", Sprite = sprite }
            }, CupboardLayer);

            if (!isRunning)
            {
                container.Add(new CuiButton()
                {
                    RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "5 -20", OffsetMax = "25 0" },
                    Button = { Command = $"UI_BuildingController open", Color = "0.31 0.64 0.89 0.5", Sprite = "assets/icons/gear.png" }
                }, CupboardLayer);
            }

            CuiHelper.AddUi(player, container);
        }

        private IEnumerator PreloadImages(BasePlayer player)
        {
            if (player == null || !player.IsConnected) yield break;
            for (var i = 0; i < config.BuildingImages.Count; i++)
            {
                CuiElementContainer temp = new CuiElementContainer();

                foreach (var blockInfo in config.BuildingImages[i])
                {
                    if (string.IsNullOrEmpty(blockInfo.Url)) continue;
                    temp.Add(new CuiElement()
                    {
                        Parent = "Hud",
                        Name = $".{i}",
                        DestroyUi = $".{i}",
                        Components =
                        {
                            new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "0 0" },
                            new CuiRawImageComponent { Png = (string) ImageLibrary?.Call("GetImage", blockInfo.Title) }
                        }
                    });
                    CuiHelper.AddUi(player, temp);
                    yield return new WaitForSeconds(1.0f);
                    CuiHelper.DestroyUi(player, $".{i}");
                }
            }
            StopCoroutine(player);
        }

        #endregion

        #region Language

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Lang_UpdateAll"] = "Skin update for all your buildings has started...",
                ["Lang_UpdateBuilding"] = "Skin update for selected building has started...",
                ["Lang_UpdateAllTarget"] = "Skin update for all players buildings has started...",
                ["Lang_UpdateProgress"] = "Please wait for the building skin update to finish.",
                ["Lang_UpdateCompleted"] = "Building skin update completed.\nUpdated {0} of {1} building blocks.",
                ["Lang_UpdateNotRequired"] = "All building blocks already have your chosen skin.",
                ["Lang_NotFoundBlocks"] = "No available buildings found for the selected player.",
                ["Lang_NotFoundPlayer"] = "Player not found. Use only the Steam Id of the player.",
                ["Lang_NotFoundBuilding"] = "Building not found. Get closer to the building and repeat again.",
                ["Lang_NotOwnerBuilding"] = "You are not the owner of this building.",
                ["Lang_BuildingBlocked"] = "You can't use this command if the building is blocked.",
                ["Lang_NoPermissions"] = "You don't have permission to use this command.",
                ["Lang_InterfaceTitle"] = "Choose a default skin for the building block",
                ["Lang_InterfaceDescr"] = "The skin will be automatically applied to building blocks.",
                ["Lang_ChangeHammer"] = "Change the skin of a building block with a hammer",
                ["Lang_NeedsRepair"] = "Allow skin changing with a hammer if a building needs repair",
                ["Lang_EnableAnimation"] = "Allow building block skin update animation",
                ["Lang_InterfaceApply"] = "Apply",
                ["Lang_SkinInstalled"] = "Installed",
                ["Lang_Unavailable"] = "Unavailable",
                ["Lang_MenuSettings"] = "Settings",
                ["Lang_ColorSettings"] = "Set color",
                ["Lang_Randomcolor"] = "Use random color",
                ["Lang_SettingEnable"] = "On",
                ["Lang_SettingDisable"] = "Off",
                ["Lang_TcChangeSkin"] = "Change building skin",
                ["Lang_TcWait"] = "Wait...",
                ["Wood"] = "Wood skin",
                ["Stone"] = "Stone skin",
                ["Metal"] = "Metal skin",
                ["TopTier"] = "TopTier skin",
                ["Adobe"] = "Adobe skin",
                ["Brick"] = "Brick skin",
                ["Brutalist"] = "Brutalist skin",
                ["Container"] = "Container skin",
                ["Frontier"] = "Frontier skin",
                ["Gingerbread"] = "Gingerbread skin"
            }, this);

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Lang_UpdateAll"] = "Обновление скина для всех ваших построек началось...",
                ["Lang_UpdateBuilding"] = "Обновление скина для выбранной постройки началось...",
                ["Lang_UpdateAllTarget"] = "Обновление скина для всех построек игрока началось...",
                ["Lang_UpdateProgress"] = "Пожалуйста, дождитесь завершения обновления скина построек.",
                ["Lang_UpdateCompleted"] = "Обновление скина построек завершено.\nОбновлено {0} из {1} строительных блоков.",
                ["Lang_UpdateNotRequired"] = "Все строительные блоки уже имеют выбранный вами скин.",
                ["Lang_NotFoundBlocks"] = "Не найдено доступных построек для выбранного игрока.",
                ["Lang_NotFoundPlayer"] = "Игрок не найден. Используйте только Steam Id игрока.",
                ["Lang_NotFoundBuilding"] = "Постройка не найдена. Подойдите ближе к постройке и повторите снова.",
                ["Lang_NotOwnerBuilding"] = "Вы не являетесь владельцем этой постройки.",
                ["Lang_BuildingBlocked"] = "Вы не можете использовать эту команду в зоне блокировки строительства.",
                ["Lang_NoPermissions"] = "У вас нет разрешения на использование этой команды.",
                ["Lang_InterfaceTitle"] = "Выберите скин по умолчанию для строительного блока",
                ["Lang_InterfaceDescr"] = "Скин будет автоматически применяться к постройке.",
                ["Lang_ChangeHammer"] = "Изменять скин постройки при помощи киянки",
                ["Lang_NeedsRepair"] = "Разрешить смену скина киянкой, если требуется ремонт постройки",
                ["Lang_EnableAnimation"] = "Разрешить анимацию обновления скина постройки",
                ["Lang_InterfaceApply"] = "Применить",
                ["Lang_SkinInstalled"] = "Установлен",
                ["Lang_Unavailable"] = "Недоступен",
                ["Lang_MenuSettings"] = "Настройки",
                ["Lang_ColorSettings"] = "Выбор цвета",
                ["Lang_Randomcolor"] = "Случайный цвет",
                ["Lang_SettingEnable"] = "Вкл",
                ["Lang_SettingDisable"] = "Выкл",
                ["Lang_TcChangeSkin"] = "Изменить скин постройки",
                ["Lang_TcWait"] = "Ожидайте...",
                ["Wood"] = "Деревянный скин",
                ["Stone"] = "Каменный скин",
                ["Metal"] = "Металлический скин",
                ["TopTier"] = "МВК скин",
                ["Adobe"] = "Саманный скин",
                ["Brick"] = "Кирпичный скин",
                ["Brutalist"] = "Брутализм скин",
                ["Container"] = "Контейнерный скин",
                ["Frontier"] = "Фронтир скин",
                ["Gingerbread"] = "Пряничный скин"
            }, this, "ru");
        }

        #endregion

        #region Data

        private StoredData storedData;

        private class StoredData
        {
            public Dictionary<ulong, Data> PlayerData = new Dictionary<ulong, Data>();
        }

        private class Data
        {
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool ChangeHammer;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool NeedsRepair;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool EnableAnimation;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool RandomColor;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public uint Color;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public ulong Wood;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public ulong Stone;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public ulong Metal;
            [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public ulong TopTier;
        }

        private void SaveData()
        {
            if (storedData != null)
            {
                Interface.Oxide.DataFileSystem.WriteObject($"{Name}_Data", storedData, true);
            }
        }

        private void LoadData()
        {
            storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>($"{Name}_Data");
            if (storedData == null)
            {
                storedData = new StoredData();
                SaveData();
            }

            foreach (var playerData in storedData.PlayerData.Values)
            {
                playerData.Wood = config.BuildingImages[0].Any(b => b.SkinId == playerData.Wood) ? playerData.Wood : 0;
                playerData.Stone = config.BuildingImages[1].Any(b => b.SkinId == playerData.Stone) ? playerData.Stone : 0;
                playerData.Metal = config.Bui

Code is above, lines changed are 542 (commented out) and 558 (added string.Format)

Replux
Any way you can just upload a file here or give the lines of code to change?
4wMY1wt1Zv0eSnP.png MrScrubby

Code is above, lines changed are 542 (commented out) and 558 (added string.Format)

Oh you gave me the whole
plugin code. I can just copy and paste it into the existing plugin and reload right? Thank you in advance!

Yeah that will work, sorry for the late reply.

Replux
Oh you gave me the whole
plugin code. I can just copy and paste it into the existing plugin and reload right? Thank you in advance!
q5hGuTPfXyJYHpv.png MrScrubby

Yeah that will work, sorry for the late reply.

Thank you for the help!
mtKJlLALh6XRl53.png MrScrubby

Yeah that will work, sorry for the late reply.

Since we are on this topic, any idea if the button to change skin could be moved since the sort button plugin is also there? Or the sort button could be moved? Not sure if there is any solution that could be made for this :D

Replux

Since we are on this topic, any idea if the button to change skin could be moved since the sort button plugin is also there? Or the sort button could be moved? Not sure if there is any solution that could be made for this :D

Yeah, just change the OffsetX for the three tool cupboards in the SortButton config to 360.5