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

FREE CupboardInspector : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using UnityEngine;
 
namespace Oxide.Plugins
{
    [Info("Cupboard Inspector", "Kaktus", "1.0.0")]
    [Description("Admin visual audit tool for group-limited servers. Scans cupboards over the authorization limit, draws world markers, provides UI with teleport and pagination.")]
    public class CupboardInspector : RustPlugin
    {
        private const string PermUse = "cupboardinspector.use";
        private const string UiLayer = "CupboardInspector.UI";
        private const int ItemsPerPage = 4;

        private Configuration _config;

        private Dictionary<ulong, List<ViolationInfo>> _playerViolations = new();
        private Dictionary<ulong, int> _playerPages = new();

        #region Config

        private class Configuration
        {
            [JsonProperty("Max authorized players allowed in cupboard")]
            public int MaxAuthorized = 2;

            [JsonProperty("Marker duration (seconds)")]
            public float MarkerDuration = 30f;

            [JsonProperty("Marker height offset")]
            public float MarkerHeight = 2.0f;

            [JsonProperty("Marker line height")]
            public float MarkerLineHeight = 25f;

            [JsonProperty("Draw arrows in world")]
            public bool DrawArrows = true;

            [JsonProperty("Draw text in world")]
            public bool DrawText = true;

            [JsonProperty("UI Anchor Min")]
            public string UiAnchorMin = "0.25 0.22";

            [JsonProperty("UI Anchor Max")]
            public string UiAnchorMax = "0.75 0.78";

            [JsonProperty("Panel Color")]
            public string PanelColor = "0.10 0.10 0.10 0.97";

            [JsonProperty("Header Color")]
            public string HeaderColor = "0.46 0.73 0.00 1.0";

            [JsonProperty("Row Color")]
            public string RowColor = "0.14 0.14 0.14 0.90";

            [JsonProperty("Row Alt Color")]
            public string RowAltColor = "0.16 0.16 0.16 0.90";

            [JsonProperty("Button Color")]
            public string ButtonColor = "0.20 0.20 0.20 1.0";

            [JsonProperty("TP Button Color")]
            public string TpButtonColor = "0.20 0.55 0.80 1.0";

            [JsonProperty("Danger Button Color")]
            public string DangerButtonColor = "0.91 0.30 0.24 1.0";

            [JsonProperty("Text Color")]
            public string TextColor = "1 1 1 1";

            [JsonProperty("Muted Text Color")]
            public string MutedTextColor = "0.60 0.60 0.60 1.0";
        }

        protected override void LoadDefaultConfig()
        {
            _config = new Configuration();
            PrintWarning("Creating new config file.");
        }

        private void LoadConfigValues()
        {
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) throw new JsonException();
            }
            catch
            {
                PrintWarning("Config is invalid, generating a new one.");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(_config, true);

        #endregion

        #region Models

        private class ViolationInfo
        {
            public Vector3 Position;
            public int Count;
            public string OwnerName;
            public List<string> Names = new List<string>();
        }

        #endregion

        #region Hooks

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
            LoadConfigValues();
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
                DestroyUi(player);

            _playerViolations.Clear();
            _playerPages.Clear();
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            DestroyUi(player);
            _playerViolations.Remove(player.userID);
            _playerPages.Remove(player.userID);
        }

        #endregion

        #region Chat Commands

        [ChatCommand("cupcheck")]
        private void CmdCupCheck(BasePlayer player, string command, string[] args)
        {
            if (!HasAccess(player))
            {
                SendReply(player, "You do not have permission to use this command.");
                return;
            }

            var violations = FindViolations();

            _playerViolations[player.userID] = violations;
            _playerPages[player.userID] = 0;

            DrawUi(player);

            if (violations.Count == 0)
            {
                SendReply(player, "<color=#76B900>[Cupboard Inspector]</color> No violations found.");
                return;
            }

            DrawWorldMarkers(player, violations);
            SendReply(player,
                $"<color=#76B900>[Cupboard Inspector]</color> Found " +
                $"<color=#FFB800>{violations.Count}</color> violation(s). " +
                $"Markers drawn for {_config.MarkerDuration:0} sec.");
        }

        #endregion

        #region Console Commands

        [ConsoleCommand("cupinspect.close")]
        private void CCmdClose(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null) return;

            DestroyUi(player);
            _playerViolations.Remove(player.userID);
            _playerPages.Remove(player.userID);
        }

        [ConsoleCommand("cupinspect.rescan")]
        private void CCmdRescan(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !HasAccess(player)) return;

            var violations = FindViolations();
            _playerViolations[player.userID] = violations;
            _playerPages[player.userID] = 0;

            DrawUi(player);
            DrawWorldMarkers(player, violations);
        }

        [ConsoleCommand("cupinspect.page")]
        private void CCmdPage(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !HasAccess(player)) return;

            var pageStr = arg.GetString(0, "0");
            if (!int.TryParse(pageStr, out var page)) return;

            _playerPages[player.userID] = page;
            DrawUi(player);
        }

        [ConsoleCommand("cupinspect.tp")]
        private void CCmdTeleport(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !HasAccess(player)) return;

            var indexStr = arg.GetString(0, "-1");
            if (!int.TryParse(indexStr, out var index)) return;

            if (!_playerViolations.TryGetValue(player.userID, out var violations))
                return;

            if (index < 0 || index >= violations.Count)
                return;

            var target = violations[index].Position + new Vector3(0f, 2f, 0f);
            player.Teleport(target);

            SendReply(player,
                $"<color=#76B900>[Cupboard Inspector]</color> Teleported to violation " +
                $"<color=#FFB800>#{index + 1}</color> " +
                $"(Owner: <color=#76B900>{violations[index].OwnerName}</color>)");
        }

        #endregion

        #region Core Logic

        private bool HasAccess(BasePlayer player)
        {
            if (player == null) return false;
            return player.IsAdmin ||
                   permission.UserHasPermission(player.UserIDString, PermUse);
        }

        private List<ViolationInfo> FindViolations()
        {
            var result = new List<ViolationInfo>();

            foreach (var entity in BaseNetworkable.serverEntities)
            {
                var cp = entity as BuildingPrivlidge;
                if (cp == null || cp.IsDestroyed)
                    continue;

                var authList = cp.authorizedPlayers;
                if (authList == null || authList.Count <= _config.MaxAuthorized)
                    continue;

                var info = new ViolationInfo
                {
                    Position = cp.transform.position,
                    Count = authList.Count,
                    OwnerName = "Unknown",
                    Names = new List<string>()
                };

                foreach (var steamId in authList)
                {
                    var name = GetPlayerName(steamId);
                    info.Names.Add(name);
                }

                if (info.Names.Count > 0)
                    info.OwnerName = info.Names[0];

                result.Add(info);
            }

            return result
                .OrderByDescending(v => v.Count)
                .ThenBy(v => v.Position.x)
                .ToList();
        }

        private string GetPlayerName(ulong steamId)
        {
            var online = BasePlayer.activePlayerList
                .FirstOrDefault(p => p.userID == steamId);
            if (online != null) return online.displayName;

            var sleeping = BasePlayer.sleepingPlayerList
                .FirstOrDefault(p => p.userID == steamId);
            if (sleeping != null) return sleeping.displayName;

            return steamId.ToString();
        }

        #endregion

        #region World Markers

        private void DrawWorldMarkers(BasePlayer admin, List<ViolationInfo> violations)
        {
            if (admin == null || violations == null || violations.Count == 0)
                return;

            foreach (var v in violations)
            {
                var target = v.Position + new Vector3(0f, _config.MarkerHeight, 0f);

                if (_config.DrawArrows)
                {

                    admin.SendConsoleCommand(
                        "ddraw.line",
                        _config.MarkerDuration,
                        Color.green,
                        target,
                        target + new Vector3(0f, _config.MarkerLineHeight, 0f));


                    admin.SendConsoleCommand(
                        "ddraw.arrow",
                        _config.MarkerDuration,
                        Color.yellow,
                        target + new Vector3(0f, 3f, 0f),
                        target,
                        0.25f);
                }

                if (_config.DrawText)
                {
                    var authNames = string.Join(", ", v.Names);

                    var markerText =
                        $"<size=10>" +
                        $"VIOLATION ({v.Count})\n" +
                        $"Owner: {v.OwnerName}\n" +
                        $"Auth: {authNames}\n" +
                        $"Pos: {v.Position.x:0}, {v.Position.y:0}, {v.Position.z:0}" +
                        $"</size>";

                    admin.SendConsoleCommand(
                        "ddraw.text",
                        _config.MarkerDuration,
                        Color.green,
                        target + new Vector3(0f, 0.5f, 0f),
                        markerText);
                }


                admin.SendConsoleCommand(
                    "ddraw.sphere",
                    _config.MarkerDuration,
                    Color.red,
                    target,
                    0.35f);
            }
        }

        #endregion

        #region UI

        private void DrawUi(BasePlayer player)
        {
            DestroyUi(player);

            if (!_playerViolations.TryGetValue(player.userID, out var violations))
                violations = new List<ViolationInfo>();

            if (!_playerPages.TryGetValue(player.userID, out var page))
                page = 0;

            var totalPages = Math.Max(1,
                (int)Math.Ceiling((double)violations.Count / ItemsPerPage));

            if (page >= totalPages) page = totalPages - 1;
            if (page < 0) page = 0;

            var pageItems = violations
                .Skip(page * ItemsPerPage)
                .Take(ItemsPerPage)
                .ToList();

            var container = new CuiElementContainer();


            container.Add(new CuiPanel
            {
                Image = { Color = _config.PanelColor },
                RectTransform =
                {
                    AnchorMin = _config.UiAnchorMin,
                    AnchorMax = _config.UiAnchorMax
                },
                CursorEnabled = true
            }, "Overlay", UiLayer);


            container.Add(new CuiPanel
            {
                Image = { Color = _config.HeaderColor },
                RectTransform =
                {
                    AnchorMin = "0 0.90",
                    AnchorMax = "1 1"
                }
            }, UiLayer, UiLayer + ".Header");

            container.Add(new CuiLabel
            {
                Text =
                {
                    Text = "CUPBOARD INSPECTOR",
                    FontSize = 14,
                    Align = TextAnchor.MiddleCenter,
                    Color = _config.TextColor
                },
                RectTransform =
                {
                    AnchorMin = "0 0",
                    AnchorMax = "0.85 1"
                }
            }, UiLayer + ".Header");


            container.Add(new CuiButton
            {
                Button =
                {
                    Color = "0.91 0.30 0.24 1.0",
                    Command = "cupinspect.close"
                },
                RectTransform =
                {
                    AnchorMin = "0.90 0.15",
                    AnchorMax = "0.99 0.85"
                },
                Text =
                {
                    Text = "✕",
                    FontSize = 14,
                    Align = TextAnchor.MiddleCenter,
                    Color = _config.TextColor
                }
            }, UiLayer + ".Header");


            var summaryText = violations.Count == 0
                ? "No violations found. Authorization limits are clean."
                : $"Found {violations.Count} violation(s)  |  Page {page + 1} / {totalPages}";

            var summaryColor = violations.Count == 0
                ? "0.46 0.73 0 1"
                : "1.0 0.72 0 1";

            container.Add(new CuiLabel
            {
                Text =
                {
                    Text = summaryText,
                    FontSize = 11,
                    Align = TextAnchor.MiddleCenter,
                    Color = summaryColor
                },
                RectTransform =
                {
                    AnchorMin = "0.05 0.82",
                    AnchorMax = "0.95 0.89"
                }
            }, UiLayer);


            var yTop = 0.80f;
            var rowH = 0.145f;
            var gap = 0.01f;

            for (int i = 0; i < pageItems.Count; i++)
            {
                var item = pageItems[i];
                var globalIndex = page * ItemsPerPage + i;
                var rowTop = yTop - (i * (rowH + gap));
                var rowBot = rowTop - rowH;

                var rowColor = i % 2 == 0
                    ? _config.RowColor
                    : _config.RowAltColor;

                var rowId = UiLayer + $".Row{i}";


                container.Add(new CuiPanel
                {
                    Image = { Color = rowColor },
                    RectTransform =
                    {
                        AnchorMin = $"0.03 {rowBot}",
                        AnchorMax = $"0.97 {rowTop}"
                    }
                }, UiLayer, rowId);


                container.Add(new CuiLabel
                {
                    Text =
                    {
                        Text = $"#{globalIndex + 1}",
                        FontSize = 14,
                        Align = TextAnchor.MiddleCenter,
                        Color = _config.HeaderColor
                    },
                    RectTransform =
                    {
                        AnchorMin = "0.0 0.0",
                        AnchorMax = "0.06 1.0"
                    }
                }, rowId);


                var authNames = string.Join(", ", item.Names.Take(4));
                if (item.Names.Count > 4)
                    authNames += $" (+{item.Names.Count - 4})";

                var infoText =
                    $"Auth: <color=#FFB800>{item.Count}</color>  |  " +
                    $"Owner: <color=#76B900>{item.OwnerName}</color>\n" +
                    $"Players: {authNames}\n" +
                    $"Pos: {item.Position.x:0}, {item.Position.y:0}, {item.Position.z:0}";

                container.Add(new CuiLabel
                {
                    Text =
                    {
                        Text = infoText,
                        FontSize = 10,
                        Align = TextAnchor.MiddleLeft,
                        Color = _config.TextColor
                    },
                    RectTransform =
                    {
                        AnchorMin = "0.07 0.05",
                        AnchorMax = "0.82 0.95"
                    }
                }, rowId);


                container.Add(new CuiButton
                {
                    Button =
                    {
                        Color = _config.TpButtonColor,
                        Command = $"cupinspect.tp {globalIndex}"
                    },
                    RectTransform =
                    {
                        AnchorMin = "0.84 0.20",
                        AnchorMax = "0.98 0.80"
                    },
                    Text =
                    {
                        Text = "TP",
                        FontSize = 12,
                        Align = TextAnchor.MiddleCenter,
                        Color = _config.TextColor
                    }
                }, rowId);
            }


            if (violations.Count == 0)
            {
                container.Add(new CuiLabel
                {
                    Text =
                    {
                        Text = "All clear! No authorization violations detected.",
                        FontSize = 13,
                        Align = TextAnchor.MiddleCenter,
                        Color = _config.TextColor
                    },
                    RectTransform =
                    {
                        AnchorMin = "0.10 0.40",
                        AnchorMax = "0.90 0.60"
                    }
                }, UiLayer);
            }




            container.Add(new CuiButton
            {
                Button =
                {
                    Color = _config.ButtonColor,
                    Command = "cupinspect.rescan"
                },
                RectTransform =
                {
                    AnchorMin = "0.03 0.02",
                    AnchorMax = "0.20 0.10"
                },
                Text =
                {
                    Text = "RESCAN",
                    FontSize = 11,
                    Align = TextAnchor.MiddleCenter,
                    Color = _config.TextColor
                }
            }, UiLayer);


            if (page > 0)
            {
                container.Add(new CuiButton
                {
                    Button =
                    {
                        Color = _config.ButtonColor,
                        Command = $"cupinspect.page {page - 1}"
                    },
                    RectTransform =
                    {
                        AnchorMin = "0.35 0.02",
                        AnchorMax = "0.48 0.10"
                    },
                    Text =
                    {
                        Text = "◀ PREV",
                        FontSize = 11,
                        Align = TextAnchor.MiddleCenter,
                        Color = _config.TextColor
                    }
                }, UiLayer);
            }


            container.Add(new CuiLabel
            {
                Text =
                {
                    Text = $"{page + 1} / {totalPages}",
                    FontSize = 11,
                    Align = TextAnchor.MiddleCenter,
                    Color = _config.MutedTextColor
                },
                RectTransform =
                {
                    AnchorMin = "0.48 0.02",
                    AnchorMax = "0.52 0.10"
                }
            }, UiLayer);


            if (page < totalPages - 1)
            {
                container.Add(new CuiButton
                {
                    Button =
                    {
                        Color = _config.ButtonColor,
                        Command = $"cupinspect.page {page + 1}"
                    },
                    RectTransform =
                    {
                        AnchorMin = "0.52 0.02",
                        AnchorMax = "0.65 0.10"
                    },
                    Text =
                    {
                        Text = "NEXT ▶",
                        FontSize = 11,
                        Align = TextAnchor.MiddleCenter,
                        Color = _config.TextColor
                    }
                }, UiLayer);
            }


            container.Add(new CuiButton
            {
                Button =
                {
                    Color = _config.DangerButtonColor,
                    Command = "cupinspect.close"
                },
                RectTransform =
                {
                    AnchorMin = "0.80 0.02",
                    AnchorMax = "0.97 0.10"
                },
                Text =
                {
                    Text = "CLOSE",
                    FontSize = 11,
                    Align = TextAnchor.MiddleCenter,
                    Color = _config.TextColor
                }
            }, UiLayer);

            CuiHelper.AddUi(player, container);
        }

        private void DestroyUi(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, UiLayer);
        }

        #endregion
    }
}

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