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

FREE MirrorPanel : 1.0.5 1.0.5

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Collections;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine.Networking;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("MirrorPanel", "tama", "1.0.5")]
    public class MirrorPanel : RustPlugin
    {
        #region [Vars]
        [PluginReference] private Plugin MirrorAlerts = null;

        private const String Layer = "MirrorPanel.Layer";

        private static InterfaceBuilder _interface = null;
        private static ImageUI ImageUi = null;
        private static MirrorPanel _ = null;

        private HashSet<UInt64> updatePanel = new HashSet<UInt64>();
        private HashSet<UInt64> openButton = new HashSet<UInt64>();
        public List<UInt64> lootedContainerPlayers = new List<UInt64>();
        private Dictionary<UInt64, DateTime> _cooldownPlayer = new Dictionary<UInt64, DateTime>();

        private Dictionary<String, String> Button = new Dictionary<String, String>()
        {
            ["Kits"] = "/kit",
            ["Report"] = "/report",
            ["chat"] = "/chat",
            ["store"] = "/store" // Добавлена кнопка
        };

        private Int32 Online = 0;
        private Timer updateTimer;
        #endregion

        #region [Oxide-Api]
        private void Init() => _ = this;

        private void OnServerInitialized()
        {
            ImageUi = new ImageUI();
            ImageUi.DownloadImage();

            // НАКРУТКА: Добавляем 22 к текущему онлайну при инициализации
            Online = BasePlayer.activePlayerList.Count + 22;

            updateTimer = timer.Every(5f, () => UpdatePanel());
        }

        private void Unload()
        {
            if (updateTimer != null)
            {
                updateTimer.Destroy();

                updateTimer = null;
            }

            if (ImageUi != null)
            {
                ImageUi.UnloadImages();

                ImageUi = null;
            }

            InterfaceBuilder.DestroyAll();

            if (updatePanel != null)
            {
                updatePanel.Clear();

                updatePanel = null;
            }

            if (openButton != null)
            {
                openButton.Clear();

                openButton = null;
            }

            if (Button != null)
            {
                Button.Clear();

                Button = null;
            }

            _ = null;
        }
        #endregion

        #region [Rust-Api]
        private void OnPlayerConnected(BasePlayer player)
        {
            // ИЗМЕНЕНИЕ: Убрано автоматическое добавление в updatePanel.
            // Теперь при входе панель считается закрытой (только Лого).
            if (updatePanel.Contains(player.userID)) 
                updatePanel.Remove(player.userID);

            DrawUI(player);
        }

        private void OnEntityEnter(TriggerWorkbench trigger, BasePlayer player)
        {
            if (player == null || player.IsNpc || lootedContainerPlayers.Contains(player.userID)) return;

            CuiHelper.DestroyUi(player, Layer);

            lootedContainerPlayers.Add(player.userID);
        }

        private void OnEntityLeave(TriggerWorkbench trigger, BasePlayer player)
        {
            if (player == null || player.IsNpc || !lootedContainerPlayers.Contains(player.userID)) return;

            DrawUI(player);

            lootedContainerPlayers.Remove(player.userID);
        }
        #endregion

        #region [API]
        private Boolean IsUpdatePanel(UInt64 steamId) => updatePanel.Contains(steamId) && !lootedContainerPlayers.Contains(steamId);
        #endregion

        #region [Command]
        [ConsoleCommand("UI_MirrorPanel")]
        private void MirrorPanelUIHandler(ConsoleSystem.Arg args)
        {
            BasePlayer player = args?.Player();
            if (player == null || !args.HasArgs() || _cooldownPlayer.ContainsKey(player.userID) && _cooldownPlayer[player.userID].Subtract(DateTime.Now).TotalSeconds >= 0) return;

            _cooldownPlayer[player.userID] = DateTime.Now.AddSeconds(0.2f);

            switch (args.Args[0])
            {
                case "logo":
                    {
                        if (updatePanel.Contains(player.userID))
                            updatePanel.Remove(player.userID);
                        else
                            updatePanel.Add(player.userID);

                        DrawUI(player);
                        break;
                    }
                case "button":
                    {
                        if (openButton.Contains(player.userID))
                        {
                            openButton.Remove(player.userID);

                            DestroyButtons(player);
                        }
                        else
                        {
                            openButton.Add(player.userID);

                            DrawButtonUI(player);
                        }
                        break;
                    }
            }
        }
        #endregion

        #region [InterfaceBuilder]
        private class InterfaceBuilder
        {
            public static InterfaceBuilder Instance;
            public const String Layer = "MirrorPanel.Layer";
            public Dictionary<String, String> Interfaces;

            public InterfaceBuilder()
            {
                Instance = this;
                Interfaces = new Dictionary<String, String>();

                BuildingPlayer_OpenMenu();

                BuildingPlayer_CloseMenu();

                Building_Button_DropMenu();
            }

            public static void AddInterface(String name, String json)
            {
                if (Instance.Interfaces.ContainsKey(name))
                {
                    _.PrintError($"Error! Tried to add existing cui elements! -> {name}");
                    return;
                }

                Instance.Interfaces.Add(name, json);
            }

            public static String GetInterface(String name)
            {
                String json = String.Empty;
                if (Instance != null && Instance.Interfaces.TryGetValue(name, out json) == false)
                {
                    _.PrintWarning($"Warning! UI elements not found by name! -> {name}");
                }

                return json;
            }

            public static void DestroyAll()
            {
                foreach (BasePlayer player in BasePlayer.activePlayerList)
                    CuiHelper.DestroyUi(player, Layer);
            }

            private void BuildingPlayer_OpenMenu()
            {
                CuiElementContainer container = new CuiElementContainer();

                container.Add(new CuiPanel
                {
                    RectTransform = { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Image = { Color = "0 0 0 0" }
                }, "Overlay", Layer, Layer);

                container.Add(new CuiElement
                {
                    Name = $"{Layer}.L",
                    Parent = Layer,
                    Components =
                    {
                        new CuiRawImageComponent { Png = ImageUi.GetImage("Logo"), Sprite = "assets/icons/loading.png" },
                        new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 -31", OffsetMax = "31 -5" }
                    }
                });

                container.Add(new CuiButton
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Button = { Color = "0 0 0 0", Command = "UI_MirrorPanel logo" },
                    Text = { Text = "" }
                }, $"{Layer}.L");

                container.Add(new CuiLabel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "33 -36", OffsetMax = "208 0" },
                    Text = { Text = $"<color=#FF0000>SABR</color> RUST №1", Color = "1 1 1 1", Align = TextAnchor.MiddleLeft, FontSize = 22, Font = "robotocondensed-bold.ttf" }
                }, Layer);

                container.Add(new CuiButton
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 -54", OffsetMax = "51 -33" },
                    Button = { Color = "0 0 0 0", Command = "UI_MirrorPanel button" },
                    Text = { Text = "%MENU%", Color = "0.92 0.92 0.92 1.00", Align = TextAnchor.MiddleCenter, FontSize = 16, Font = "robotocondensed-bold.ttf" }
                }, Layer);

                container.Add(new CuiElement
                {
                    Name = $"{Layer}.Online",
                    Parent = Layer,
                    Components =
                    {
                        new CuiRawImageComponent { Png = ImageUi.GetImage("Online"), Sprite = "assets/icons/loading.png", Color = "1 1 1 0.8" },
                        new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "54 -54", OffsetMax = "99 -33" }
                    }
                });

                container.Add(new CuiElement
                {
                    Name = $"{Layer}.Online.Text",
                    Parent = $"{Layer}.Online",
                    Components =
                    {
                        new CuiTextComponent { Text = $"%ONLINE%/{ConVar.Server.maxplayers}", Color = "1 1 1 0.95", Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "robotocondensed-bold.ttf" },
                        new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" }
                    },
                });

                container.Add(new CuiElement
                {
                    Name = $"{Layer}.Time",
                    Parent = Layer,
                    Components =
                    {
                        new CuiRawImageComponent { Png = ImageUi.GetImage("Time"), Sprite = "assets/icons/loading.png", Color = "1 1 1 0.8" },
                        new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "102 -54", OffsetMax = "140 -33" }
                    }
                });

                container.Add(new CuiElement
                {
                    Name = $"{Layer}.Time.Text",
                    Parent = $"{Layer}.Time",
                    Components =
                    {
                        new CuiTextComponent { Text = "%TIME%", Color = "1 1 1 0.95", Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "robotocondensed-bold.ttf" },
                        new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" }
                    },
                });

                AddInterface("UI_OPEN_MENU", container.ToJson());
            }

            private void BuildingPlayer_CloseMenu()
            {
                CuiElementContainer container = new CuiElementContainer();

                container.Add(new CuiPanel
                {
                    RectTransform = { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Image = { Color = "0 0 0 0" }
                }, "Overlay", Layer, Layer);

                container.Add(new CuiElement
                {
                    Name = $"{Layer}.L",
                    Parent = Layer,
                    Components =
                    {
                        new CuiRawImageComponent { Png = ImageUi.GetImage("Logo"), Sprite = "assets/icons/loading.png" },
                        new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 -31", OffsetMax = "31 -5" }
                    }
                });

                container.Add(new CuiButton
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Button = { Color = "0 0 0 0", Command = "UI_MirrorPanel logo" },
                    Text = { Text = "" }
                }, $"{Layer}.L");

                AddInterface("UI_CLOSE_MENU", container.ToJson());
            }

            private void Building_Button_DropMenu()
            {
                CuiElementContainer container = new CuiElementContainer();

                container.Add(new CuiPanel
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"5 %OFFSET_MIN%", OffsetMax = $"130 %OFFSET_MAX%" },
                    Image = { Color = "0 0 0 0" }
                }, Layer, "%NAME_BUTTON%");

                container.Add(new CuiElement
                {
                    Name = "Image",
                    Parent = "%NAME_BUTTON%",
                    Components =
                    {
                        new CuiImageComponent { Png = "%PNG_BUTTON%", Color = "0.92 0.92 0.92 1.00" },
                        new CuiRectTransformComponent { AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "0 -10", OffsetMax = "20 10" }
                    }
                });

                container.Add(new CuiLabel()
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "25 0", OffsetMax = "0 0" },
                    Text = { Text = "%TEXT%", Color = "0.92 0.92 0.92 1.00", Align = TextAnchor.MiddleLeft, FontSize = 12, Font = "robotocondensed-bold.ttf" }
                }, "%NAME_BUTTON%");

                container.Add(new CuiButton
                {
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" },
                    Button = { Color = "0 0 0 0", Command = $"chat.say %COMMAND%" },
                    Text = { Text = "" }
                }, "%NAME_BUTTON%");

                AddInterface("MENU_DROP_BUTTON", container.ToJson());
            }
        }
        #endregion

        #region [ImageUI]
        private class ImageUI
        {
            private const String _path = "MirrorPanel/";
            private const String _printPath = "data/" + _path;
            private readonly Dictionary<String, ImageData> _images = new Dictionary<String, ImageData>()
                {
                    { "Logo", new ImageData() },
                    { "Group 1", new ImageData() },
                    { "Online", new ImageData() },
                    { "Time", new ImageData() },
                    { "Kits", new ImageData() },
                    { "Report", new ImageData() },
                    { "chat", new ImageData() },
                    { "store", new ImageData() } // Добавлена картинка store.png
                };

            private enum ImageStatus
            {
                NotLoaded,
                Loaded,
                Failed
            }

            private class ImageData
            {
                public ImageStatus Status = ImageStatus.NotLoaded;
                public String Id { get; set; }
            }

            public String GetImage(String name)
            {
                ImageData image;
                if (_images.TryGetValue(name, out image) && image.Status == ImageStatus.Loaded)
                    return image.Id;
                return null;
            }

            public void DownloadImage()
            {
                KeyValuePair<String, ImageData>? image = null;
                foreach (KeyValuePair<String, ImageData> img in _images)
                {
                    if (img.Value.Status == ImageStatus.NotLoaded)
                    {
                        image = img;
                        break;
                    }
                }

                if (image != null)
                {
                    ServerMgr.Instance.StartCoroutine(ProcessDownloadImage(image.Value));
                }
                else
                {
                    List<String> failedImages = new List<String>();

                    foreach (KeyValuePair<String, ImageData> img in _images)
                    {
                        if (img.Value.Status == ImageStatus.Failed)
                        {
                            failedImages.Add(img.Key);
                        }
                    }

                    if (failedImages.Count > 0)
                    {
                        String images = String.Join(", ", failedImages);
                        _.PrintError($"Не удалось загрузить следующие изображения: {images}. Возможно, вы не загрузили их в папку '{_printPath}'.");
                        Interface.Oxide.UnloadPlugin(_.Name);
                    }
                    else
                    {
                        _.Puts($"{_images.Count} изображений успешно загружено!");

                        _interface = new InterfaceBuilder();
                        _.PrintWarning("Интерфейс успешно загружен!");

                        foreach (BasePlayer player in BasePlayer.activePlayerList)
                            _.OnPlayerConnected(player);
                    }
                }
            }

            public void UnloadImages()
            {
                foreach (KeyValuePair<String, ImageData> item in _images)
                    if (item.Value.Status == ImageStatus.Loaded)
                        if (item.Value?.Id != null)
                            FileStorage.server.Remove(uint.Parse(item.Value.Id), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID);

                _images?.Clear();
            }

            private IEnumerator ProcessDownloadImage(KeyValuePair<String, ImageData> image)
            {
                String url = $"file://{Interface.Oxide.DataDirectory}/{_path}{image.Key}.png";

                using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
                {
                    yield return www.SendWebRequest();

                    if (www.isNetworkError || www.isHttpError)
                    {
                        image.Value.Status = ImageStatus.Failed;
                    }
                    else
                    {
                        Texture2D tex = DownloadHandlerTexture.GetContent(www);
                        image.Value.Id = FileStorage.server.Store(tex.EncodeToPNG(), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
                        image.Value.Status = ImageStatus.Loaded;
                        UnityEngine.Object.DestroyImmediate(tex);
                    }

                    DownloadImage();
                }
            }
        }
        #endregion

        #region [Lang]
        private new void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<String, String>
            {
                ["Kits"] = "KITS",
                ["Report"] = "REPORTS",
                ["Menu"] = "MENU",
                ["chat"] = "CHAT SETTINGS",
                ["store"] = "STORE" // Добавлен английский ключ
            }, this);

            lang.RegisterMessages(new Dictionary<String, String>
            {
                ["Kits"] = "НАБОРЫ",
                ["Report"] = "ЖАЛОБЫ",
                ["Menu"] = "МЕНЮ",
                ["chat"] = "НАСТРОЙКИ ЧАТА",
                ["store"] = "КОРЗИНА" // Добавлен русский ключ
            }, this, "ru");
        }
        #endregion

        #region [Functional]
        private void DrawUI(BasePlayer player)
        {
            if (_interface == null) return;

            if (updatePanel.Contains(player.userID))
            {
                String Interface = InterfaceBuilder.GetInterface("UI_OPEN_MENU");
                if (Interface == null) return;

                Interface = Interface.Replace("%MENU%", lang.GetMessage("Menu", this, player.UserIDString));
                Interface = Interface.Replace("%ONLINE%", $"{Online}");
                Interface = Interface.Replace("%TIME%", $"{TOD_Sky.Instance.Cycle.DateTime:HH:mm}");

                CuiHelper.AddUi(player, Interface);

                if (openButton.Contains(player.userID)) DrawButtonUI(player);
            }
            else
            {
                String Interface = InterfaceBuilder.GetInterface("UI_CLOSE_MENU");
                if (Interface == null) return;

                CuiHelper.AddUi(player, Interface);
            }
        }

        private void DrawButtonUI(BasePlayer player)
        {
            Int32 Y = 0;
            foreach (KeyValuePair<String, String> button in Button)
            {
                DrawUI_ButtonDropMenu(player, Y, button.Value, button.Key, lang.GetMessage(button.Key, this, player.UserIDString));

                Y++;
            }
        }

        private void DrawUI_ButtonDropMenu(BasePlayer player, Int32 Y, String Command, String PNG, String TitleBtn)
        {
            String Interface = InterfaceBuilder.GetInterface("MENU_DROP_BUTTON");
            if (Interface == null) return;

            Interface = Interface.Replace("%NAME_BUTTON%", $"DROP_BUTTON_{Y}");
            Interface = Interface.Replace("%OFFSET_MIN%", $"{-77 - (Y * 23)}");
            Interface = Interface.Replace("%OFFSET_MAX%", $"{-57 - (Y * 23)}");
            Interface = Interface.Replace("%PNG_BUTTON%", ImageUi.GetImage(PNG));
            Interface = Interface.Replace("%TEXT%", TitleBtn);
            Interface = Interface.Replace("%COMMAND%", Command);

            CuiHelper.AddUi(player, Interface);
        }

        private void DestroyButtons(BasePlayer player)
        {
            for (Int32 Y = 0; Y < Button.Count; Y++)
                CuiHelper.DestroyUi(player, $"DROP_BUTTON_{Y}");
        }

        private void UpdatePanel()
        {
            if (updatePanel.Count == 0) return;

            try
            {
                int currentFakeOnline = BasePlayer.activePlayerList.Count + 0;
                bool onlineChanged = Online != currentFakeOnline;
                if (onlineChanged)
                    Online = currentFakeOnline;

                foreach (BasePlayer player in BasePlayer.activePlayerList)
                {
                    if (!updatePanel.Contains(player.userID) || lootedContainerPlayers.Contains(player.userID))
                        continue;

                    if (onlineChanged)
                        RefreshOnlineText(player);

                    RefreshTimeText(player);
                }
            }
            catch (Exception e)
            {
                PrintError($"Ошибка при обновлении панели: {e}");
            }
        }

        private void RefreshOnlineText(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, $"{Layer}.Online.Text");

            var container = new CuiElementContainer();
            container.Add(new CuiElement
            {
                Name = $"{Layer}.Online.Text",
                Parent = $"{Layer}.Online",
                Components =
                {
                    new CuiTextComponent { Text = $"{Online}/{ConVar.Server.maxplayers}", Color = "1 1 1 0.95", Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" }
                }
            });
            CuiHelper.AddUi(player, container);
        }

        private void RefreshTimeText(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, $"{Layer}.Time.Text");

            var container = new CuiElementContainer();
            container.Add(new CuiElement
            {
                Name = $"{Layer}.Time.Text",
                Parent = $"{Layer}.Time",
                Components =
                {
                    new CuiTextComponent { Text = TOD_Sky.Instance.Cycle.DateTime.ToString("HH:mm"), Color = "1 1 1 0.95", Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" }
                }
            });
            CuiHelper.AddUi(player, container);
        }
        #endregion
    }
}

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