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

FREE PlayerAdministration : 1.5.26 1.5.26

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/* --- Contributor information ---
 * Please follow the following set of guidelines when working on this plugin,
 * this to help others understand this file more easily.*
 * -- Authors --
 * Thimo (ThibmoRozier) <thibmorozier@live.nl>
 * rfc1920 <no@email.com>
 * Mheetu <no@email.com>
 *
 * -- Naming --
 * Avoid using non-alphabetic characters, eg: _
 * Avoid using numbers in method and class names (Upgrade methods are allowed to have these, for readability)
 * Private constants -------------------- SHOULD start with a uppercase "C" (PascalCase)
 * Private readonly fields -------------- SHOULD start with a uppercase "C" (PascalCase)
 * Private fields ----------------------- SHOULD start with a uppercase "F" (PascalCase)
 * Arguments/Parameters ----------------- SHOULD start with a lowercase "a" (camelCase)
 * Classes ------------------------------ SHOULD start with a uppercase character (PascalCase)
 * Methods ------------------------------ SHOULD start with a uppercase character (PascalCase)
 * Public properties (constants/fields) - SHOULD start with a uppercase character (PascalCase)
 * Variables ---------------------------- SHOULD start with a lowercase character (camelCase)
 *
 * -- Style --
 * Max-line-width ------- 160
 * Single-line comments - // Single-line comment
 * Multi-line comments -- Just like this comment block!
 */
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Game.Rust.Libraries;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using UnityEngine;
using RustLib = Oxide.Game.Rust.Libraries.Rust;
namespace Oxide.Plugins {
    [Info("PlayerAdministration", "ThibmoRozier", "1.5.26")]
    [Description("Allows server admins to moderate users using a GUI from within the game.")]
    public class PlayerAdministration : CovalencePlugin {
#region Plugin References
#pragma warning disable IDE0044, CS0649
        [PluginReference]
        private Plugin Economics;
        [PluginReference]
        private Plugin ServerRewards;
        [PluginReference]
        private Plugin Freeze;
        [PluginReference]
        private Plugin PermissionsManager;
        [PluginReference]
        private Plugin DiscordMessages;
        [PluginReference]
        private Plugin BetterChatMute;
        [PluginReference]
        private Plugin Backpacks;
        [PluginReference]
        private Plugin InventoryViewer;
        [PluginReference]
        private Plugin Vanish;
#pragma warning restore IDE0044, CS0649
#endregion Plugin References
#region Library Imports
        private readonly RustLib rust = Interface.Oxide.GetLibrary<RustLib>();
        private readonly Player Player = Interface.Oxide.GetLibrary<Player>();
#endregion Library Imports
#region GUI
#region Types
        /// <summary>
        /// UI Color object
        /// </summary>
        private class CuiColor {
            public byte R {
                get;
                set;
            }
            public byte G {
                get;
                set;
            }
            public byte B {
                get;
                set;
            }
            public float A {
                get;
                set;
            }
            public CuiColor(byte aRed = 255, byte aGreen = 255, byte aBlue = 255, float aAlpha = 1f) {
                R = aRed;
                G = aGreen;
                B = aBlue;
                A = aAlpha;
            }
            public override string ToString() => $"{(double)R / 255} {(double)G / 255} {(double)B / 255} {A}";
            public static readonly CuiColor Background = new CuiColor(240, 240, 240, 0.3f);
            public static readonly CuiColor BackgroundMedium = new CuiColor(76, 74, 72, 0.83f);
            public static readonly CuiColor BackgroundDark = new CuiColor(42, 42, 42, 0.93f);
            public static readonly CuiColor Button = new CuiColor(42, 42, 42, 1f);
            public static readonly CuiColor ButtonInactive = new CuiColor(168, 168, 168, 1f);
            public static readonly CuiColor ButtonDecline = new CuiColor(192, 0, 0, 1f);
            public static readonly CuiColor ButtonDanger = new CuiColor(193, 46, 42, 1f);
            public static readonly CuiColor ButtonWarning = new CuiColor(213, 133, 18, 1f);
            public static readonly CuiColor ButtonSuccess = new CuiColor(57, 132, 57, 1f);
            public static readonly CuiColor Text = new CuiColor(0, 0, 0, 1f);
            public static readonly CuiColor TextAlt = new CuiColor(255, 255, 255, 1f);
            public static readonly CuiColor TextTitle = new CuiColor(206, 66, 43, 1f);
            public static readonly CuiColor None = new CuiColor(0, 0, 0, 0f);
        }
        /// <summary>
        /// Element position object
        /// </summary>
        private class CuiPoint {
            public float X {
                get;
                set;
            }
            public float Y {
                get;
                set;
            }
            public CuiPoint(float aX = 0f, float aY = 0f) {
                X = aX;
                Y = aY;
            }
            public override string ToString() => $"{X} {Y}";
            public static readonly CuiPoint Zero = new CuiPoint();
        }
        /// <summary>
        /// UI pages to make the switching more humanly readable
        /// </summary>
        private enum UiPage {
            Main = 0, PlayersOnline, PlayersOffline, PlayersBanned, PlayerPage, PlayerPageBanned
        }
#endregion Types
#region UI object definitions
        /// <summary>
        /// Input field object
        /// </summary>
        private class CuiInputField {
            public CuiInputFieldComponent InputField {
                get;
            }
            = new CuiInputFieldComponent();
            public CuiRectTransformComponent RectTransform {
                get;
            }
            = new CuiRectTransformComponent();
            public float FadeOut {
                get;
                set;
            }
        }
#endregion UI object definitions
#region Component container
        /// <summary>
        /// Custom version of the CuiElementContainer to add InputFields
        /// </summary>
        private class CustomCuiElementContainer : CuiElementContainer {
            public string Add(CuiInputField aInputField, string aParent = Cui.ParentHud, string aName = "") {
                if (string.IsNullOrEmpty(aName)) aName = CuiHelper.GetGuid();
                if (aInputField == null) {
                    FPluginInstance.LogError($"CustomCuiElementContainer::Add > Parameter 'aInputField' is null");
                    return string.Empty;
                }
                Add(new CuiElement {
                    Name = aName, Parent = aParent, FadeOut = aInputField.FadeOut, Components = {
                        aInputField.InputField, aInputField.RectTransform
                    }
                }
                );
                return aName;
            }
        }
#endregion Component container
        /// <summary>
        /// Rust UI object
        /// </summary>
        private class Cui {
            public const string ParentHud = "Hud";
            public const string ParentOverlay = "Overlay";
            private readonly CustomCuiElementContainer FContainer = new CustomCuiElementContainer();
            private readonly BasePlayer FPlayer;
            public readonly ulong PlayerId;
            public readonly string PlayerIdString;
            public readonly float StartTime = Time.realtimeSinceStartup;
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="aPlayer">The player this object is meant for</param>
            public Cui(BasePlayer aPlayer) {
                if (aPlayer == null) {
                    FPluginInstance.LogError("Cui::Cui > Parameter 'aPlayer' is null");
                    return;
                }
                FPlayer = aPlayer;
                PlayerId = aPlayer.userID;
                PlayerIdString = aPlayer.UserIDString;
                FPluginInstance.LogDebug("Cui instance created");
            }
            /// <summary>
            /// Add a new panel
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aIndCursorEnabled">The panel requires the cursor</param>
            /// <param name="aColor">Image color</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aPng">Image PNG file path</param>
            /// <returns>New object name</returns>
            public string AddPanel(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, bool aIndCursorEnabled, CuiColor aColor = null, string aName = "", string aPng = "" ) => AddPanel(aParent, aLeftBottomAnchor, aRightTopAnchor, CuiPoint.Zero, CuiPoint.Zero, aIndCursorEnabled, aColor, aName, aPng);
            /// <summary>
            /// Add a new panel
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aLeftBottomOffset">Left(x)-Bottom(y) relative offset</param>
            /// <param name="aRightTopOffset">Right(x)-Top(y) relative offset</param>
            /// <param name="aIndCursorEnabled">The panel requires the cursor</param>
            /// <param name="aColor">Image color</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aPng">Image PNG file path</param>
            /// <returns>New object name</returns>
            public string AddPanel(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, CuiPoint aLeftBottomOffset, CuiPoint aRightTopOffset, bool aIndCursorEnabled, CuiColor aColor = null, string aName = "", string aPng = "" ) {
                if (aLeftBottomAnchor == null || aRightTopAnchor == null || aLeftBottomOffset == null || aRightTopOffset == null) {
                    FPluginInstance.LogError($"Cui::AddPanel > One of the required parameters is null");
                    return string.Empty;
                }
                CuiPanel panel = new CuiPanel {
                    RectTransform = {
                        AnchorMin = aLeftBottomAnchor.ToString(), AnchorMax = aRightTopAnchor.ToString(), OffsetMin = aLeftBottomOffset.ToString(), OffsetMax = aRightTopOffset.ToString()
                    }
                    , CursorEnabled = aIndCursorEnabled
                }
                ;
                if (!string.IsNullOrEmpty(aPng)) panel.Image = new CuiImageComponent {
                    Png = aPng
                }
                ;
                if (aColor != null) {
                    if (panel.Image == null) {
                        panel.Image = new CuiImageComponent {
                            Color = aColor.ToString()
                        }
                        ;
                    }
                    else {
                        panel.Image.Color = aColor.ToString();
                    }
                }
                FPluginInstance.LogDebug("Added panel to container");
                return FContainer.Add(panel, aParent, string.IsNullOrEmpty(aName) ? null : aName);
            }
            /// <summary>
            /// Add a new label
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aColor">Text color</param>
            /// <param name="aText">Text to show</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aFontSize">Font size</param>
            /// <param name="aAlign">Text alignment</param>
            /// <returns>New object name</returns>
            public string AddLabel(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, CuiColor aColor, string aText, string aName = "", int aFontSize = 14, TextAnchor aAlign = TextAnchor.UpperLeft ) => AddLabel(aParent, aLeftBottomAnchor, aRightTopAnchor, CuiPoint.Zero, CuiPoint.Zero, aColor, aText, aName, aFontSize, aAlign);
            /// <summary>
            /// Add a new label
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aLeftBottomOffset">Left(x)-Bottom(y) relative offset</param>
            /// <param name="aRightTopOffset">Right(x)-Top(y) relative offset</param>
            /// <param name="aColor">Text color</param>
            /// <param name="aText">Text to show</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aFontSize">Font size</param>
            /// <param name="aAlign">Text alignment</param>
            /// <returns>New object name</returns>
            public string AddLabel(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, CuiPoint aLeftBottomOffset, CuiPoint aRightTopOffset, CuiColor aColor, string aText, string aName = "", int aFontSize = 14, TextAnchor aAlign = TextAnchor.UpperLeft ) {
                if (aLeftBottomAnchor == null || aRightTopAnchor == null || aLeftBottomOffset == null || aRightTopOffset == null || aColor == null) {
                    FPluginInstance.LogError($"Cui::AddLabel > One of the required parameters is null");
                    return string.Empty;
                }
                FPluginInstance.LogDebug("Added label to container");
                return FContainer.Add(new CuiLabel {
                    Text = {
                        Text = aText ?? string.Empty, FontSize = aFontSize, Align = aAlign, Color = aColor.ToString()
                    }
                    , RectTransform = {
                        AnchorMin = aLeftBottomAnchor.ToString(), AnchorMax = aRightTopAnchor.ToString(), OffsetMin = aLeftBottomOffset.ToString(), OffsetMax = aRightTopOffset.ToString()
                    }
                }
                , aParent, string.IsNullOrEmpty(aName) ? null : aName );
            }
            /// <summary>
            /// Add a new button
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aButtonColor">Button background color</param>
            /// <param name="aTextColor">Text color</param>
            /// <param name="aText">Text to show</param>
            /// <param name="aCommand">OnClick event callback command</param>
            /// <param name="aClose">Panel to close</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aFontSize">Font size</param>
            /// <param name="aAlign">Text alignment</param>
            /// <returns>New object name</returns>
            public string AddButton(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, CuiColor aButtonColor, CuiColor aTextColor, string aText, string aCommand = "", string aClose = "", string aName = "", int aFontSize = 14, TextAnchor aAlign = TextAnchor.MiddleCenter ) => AddButton(aParent, aLeftBottomAnchor, aRightTopAnchor, CuiPoint.Zero, CuiPoint.Zero, aButtonColor, aTextColor, aText, aCommand, aClose, aName, aFontSize, aAlign );
            /// <summary>
            /// Add a new button
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aLeftBottomOffset">Left(x)-Bottom(y) relative offset</param>
            /// <param name="aRightTopOffset">Right(x)-Top(y) relative offset</param>
            /// <param name="aButtonColor">Button background color</param>
            /// <param name="aTextColor">Text color</param>
            /// <param name="aText">Text to show</param>
            /// <param name="aCommand">OnClick event callback command</param>
            /// <param name="aClose">Panel to close</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aFontSize">Font size</param>
            /// <param name="aAlign">Text alignment</param>
            /// <returns>New object name</returns>
            public string AddButton(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, CuiPoint aLeftBottomOffset, CuiPoint aRightTopOffset, CuiColor aButtonColor, CuiColor aTextColor, string aText, string aCommand = "", string aClose = "", string aName = "", int aFontSize = 14, TextAnchor aAlign = TextAnchor.MiddleCenter ) {
                if (aLeftBottomAnchor == null || aRightTopAnchor == null || aLeftBottomOffset == null || aRightTopOffset == null || aButtonColor == null || aTextColor == null ) {
                    FPluginInstance.LogError($"Cui::AddButton > One of the required parameters is null");
                    return string.Empty;
                }
                FPluginInstance.LogDebug("Added button to container");
                return FContainer.Add(new CuiButton {
                    Button = {
                        Command = aCommand ?? string.Empty, Close = aClose ?? string.Empty, Color = aButtonColor.ToString()
                    }
                    , RectTransform = {
                        AnchorMin = aLeftBottomAnchor.ToString(), AnchorMax = aRightTopAnchor.ToString(), OffsetMin = aLeftBottomOffset.ToString(), OffsetMax = aRightTopOffset.ToString()
                    }
                    , Text = {
                        Text = aText ?? string.Empty, FontSize = aFontSize, Align = aAlign, Color = aTextColor.ToString()
                    }
                }
                , aParent, string.IsNullOrEmpty(aName) ? null : aName );
            }
            /// <summary>
            /// Add a new input field
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aColor">Text color</param>
            /// <param name="aText">Text to show</param>
            /// <param name="aCharsLimit">Max character count</param>
            /// <param name="aCommand">OnChanged event callback command</param>
            /// <param name="aIndPassword">Indicates that this input should show password chars</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aFontSize">Font size</param>
            /// <param name="aAlign">Text alignment</param>
            /// <returns>New object name</returns>
            public string AddInputField(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, CuiColor aColor, string aText = "", int aCharsLimit = 100, string aCommand = "", bool aIndPassword = false, string aName = "", int aFontSize = 14, TextAnchor aAlign = TextAnchor.MiddleLeft ) => AddInputField(aParent, aLeftBottomAnchor, aRightTopAnchor, CuiPoint.Zero, CuiPoint.Zero, aColor, aText, aCharsLimit, aCommand, aIndPassword, aName, aFontSize, aAlign );
            /// <summary>
            /// Add a new input field
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aLeftBottomAnchor">Left(x)-Bottom(y) relative position</param>
            /// <param name="aRightTopAnchor">Right(x)-Top(y) relative position</param>
            /// <param name="aLeftBottomOffset">Left(x)-Bottom(y) relative offset</param>
            /// <param name="aRightTopOffset">Right(x)-Top(y) relative offset</param>
            /// <param name="fadeOut">Fade-out time</param>
            /// <param name="aColor">Text color</param>
            /// <param name="aText">Text to show</param>
            /// <param name="aCharsLimit">Max character count</param>
            /// <param name="aCommand">OnChanged event callback command</param>
            /// <param name="aIndPassword">Indicates that this input should show password chars</param>
            /// <param name="aName">The object's name</param>
            /// <param name="aFontSize">Font size</param>
            /// <returns>New object name</returns>
            public string AddInputField(string aParent, CuiPoint aLeftBottomAnchor, CuiPoint aRightTopAnchor, CuiPoint aLeftBottomOffset, CuiPoint aRightTopOffset, CuiColor aColor, string aText = "", int aCharsLimit = 100, string aCommand = "", bool aIndPassword = false, string aName = "", int aFontSize = 14, TextAnchor aAlign = TextAnchor.MiddleLeft ) {
                if (aLeftBottomAnchor == null || aRightTopAnchor == null || aLeftBottomOffset == null || aRightTopOffset == null || aColor == null) {
                    FPluginInstance.LogError($"Cui::AddInputField > One of the required parameters is null");
                    return string.Empty;
                }
                FPluginInstance.LogDebug("Added input field to container");
                return FContainer.Add(new CuiInputField {
                    InputField = {
                        Text = aText ?? string.Empty, FontSize = aFontSize, Align = aAlign, Color = aColor.ToString(), CharsLimit = aCharsLimit, Command = aCommand ?? string.Empty, IsPassword = aIndPassword
                    }
                    , RectTransform = {
                        AnchorMin = aLeftBottomAnchor.ToString(), AnchorMax = aRightTopAnchor.ToString(), OffsetMin = aLeftBottomOffset.ToString(), OffsetMax = aRightTopOffset.ToString()
                    }
                }
                , aParent, string.IsNullOrEmpty(aName) ? null : aName );
            }
            /// <summary>
            /// Add a new element
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aElement">The object itself</param>
            /// <param name="aName">The object's name</param>
            /// <returns>New object name</returns>
            public string AddElement(string aParent, CuiPanel aElement, string aName = "") => FContainer.Add(aElement, aParent, string.IsNullOrEmpty(aName) ? null : aName);
            /// <summary>
            /// Add a new element
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aElement">The object itself</param>
            /// <param name="aName">The object's name</param>
            /// <returns>New object name</returns>
            public string AddElement(string aParent, CuiLabel aElement, string aName = "") => FContainer.Add(aElement, aParent, string.IsNullOrEmpty(aName) ? null : aName);
            /// <summary>
            /// Add a new element
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aElement">The object itself</param>
            /// <param name="aName">The object's name</param>
            /// <returns>New object name</returns>
            public string AddElement(string aParent, CuiButton aElement, string aName = "") => FContainer.Add(aElement, aParent, string.IsNullOrEmpty(aName) ? null : aName);
            /// <summary>
            /// Add a new element
            /// </summary>
            /// <param name="aParent">The parent object name</param>
            /// <param name="aElement">The object itself</param>
            /// <param name="aName">The object's name</param>
            /// <returns>New object name</returns>
            public string AddElement(string aParent, CuiInputField aElement, string aName = "") => FContainer.Add(aElement, aParent, string.IsNullOrEmpty(aName) ? null : aName);
            /// <summary>
            /// Draw the UI to the player's client
            /// </summary>
            /// <returns></returns>
            public bool Draw() => CuiHelper.AddUi(FPlayer, CuiHelper.ToJson(FContainer));
            public string JSON {
                get {
                    return CuiHelper.ToJson(FContainer, true);
                }
            }
        }
#endregion GUI
#region Utility methods
        /// <summary>
        /// Add a button to the tab menu
        /// </summary>
        /// <param name="aUIObj">Cui object</param>
        /// <param name="aParent">Name of the parent object</param>
        /// <param name="aCaption">Text to show</param>
        /// <param name="aCommand">Button to execute</param>
        /// <param name="aPos">Bounds of the button</param>
        /// <param name="aIndActive">To indicate whether or not the button is active</param>
        private void AddTabMenuBtn(ref Cui aUIObj, string aParent, string aCaption, string aCommand, int aPos, bool aIndActive) {
            Vector2 dimensions = new Vector2(0.096f, 0.75f);
            Vector2 offset = new Vector2(0.005f, 0.1f);
            CuiColor btnColor = (aIndActive ? CuiColor.ButtonInactive : CuiColor.Button);
            CuiPoint lbAnchor = new CuiPoint(((dimensions.x + offset.x) * aPos) + offset.x, offset.y);
            CuiPoint rtAnchor = new CuiPoint(lbAnchor.X + dimensions.x, offset.y + dimensions.y);
            aUIObj.AddButton(aParent, lbAnchor, rtAnchor, btnColor, CuiColor.TextAlt, aCaption, (aIndActive ? string.Empty : aCommand));
        }
        /// <summary>
        /// Add a set of user buttons to the parent object
        /// </summary>
        /// <param name="aUIObj">Cui object</param>
        /// <param name="aParent">Name of the parent object</param>
        /// <param name="aUserList">List of entities</param>
        /// <param name="aCommandFmt">Base format of the command to execute (Will be completed with the user ID</param>
        /// <param name="aPage">User list page</param>
        private void AddPlayerButtons(ref Cui aUIObj, string aParent, IEnumerable<KeyValuePair<ulong, string>> aUserList, string aCommandFmt, int aPage) {
            IEnumerable<KeyValuePair<ulong, string>> userRange = aUserList.Skip(aPage * CMaxPlayerButtons).Take(CMaxPlayerButtons);
            Vector2 dimensions = new Vector2(0.194f, 0.06f);
            Vector2 offset = new Vector2(0.005f, 0.01f);
            int col = -1;
            int row = 0;
            float margin = 0.09f;
            List<string> addedNames = new List<string>();
            foreach (KeyValuePair<ulong, string> user in userRange) {
                if (++col >= CMaxPlayerCols) {
                    row++;
                    col = 0;
                }
                float calcTop = (1f - margin) - (((dimensions.y + offset.y) * row) + offset.y);
                float calcLeft = ((dimensions.x + offset.x) * col) + offset.x;
                CuiPoint lbAnchor = new CuiPoint(calcLeft, calcTop - dimensions.y);
                CuiPoint rtAnchor = new CuiPoint(calcLeft + dimensions.x, calcTop);
                int suffix = 0;
                string btnTextTemp = EscapeString(user.Value ?? "");
                string btnCommand = string.Format(aCommandFmt, user.Key);
                if (string.IsNullOrEmpty(btnTextTemp) || CUnknownNameList.Contains(btnTextTemp.ToLower())) btnTextTemp = user.Key.ToString();
                string btnText = btnTextTemp;
                while (addedNames.FindIndex(item => btnText.Equals(item, StringComparison.OrdinalIgnoreCase)) >= 0) {
                    btnText = $"{btnTextTemp} {++suffix}";
                }
                aUIObj.AddButton(aParent, lbAnchor, rtAnchor, CuiColor.Button, CuiColor.TextAlt, btnText, btnCommand, string.Empty, string.Empty, 16);
                addedNames.Add(btnText);
            }
            LogDebug("Added the player buttons to the container");
        }
        /// <summary>
        /// Log an error message to the logfile
        /// </summary>
        /// <param name="aMessage"></param>
        private void LogError(string aMessage) => LogToFile(string.Empty, $"[{DateTime.Now.ToString("hh : mm : ss")}] ERROR > {aMessage}", this);
        /// <summary>
        /// Log an informational message to the logfile
        /// </summary>
        /// <param name="aMessage"></param>
        private void LogInfo(string aMessage) => LogToFile(string.Empty, $"[{DateTime.Now.ToString("hh : mm : ss")}] INFO > {aMessage}", this);
        /// <summary>
        /// Log a debugging message to the logfile
        /// </summary>
        /// <param name="aMessage"></param>
        private void LogDebug(string aMessage) {
            if (CDebugEnabled) LogToFile(string.Empty, $"[{DateTime.Now.ToString("hh : mm : ss")}] DEBUG > {aMessage}", this);
        }
        /// <summary>
        /// Verify if a user has the specified permission
        /// </summary>
        /// <param name="aPlayer">The player</param>
        /// <param name="aPermission">Pass <see cref="string.Empty"/> to only verify <see cref="CPermUiShow"/></param>
        /// <param name="aIndReport">Indicates that issues should be reported</param>
        /// <returns></returns>
        private bool VerifyPermission(ref BasePlayer aPlayer, string aPermission, bool aIndReport = false) {
            bool result = permission.UserHasPermission(aPlayer.UserIDString, CPermUiShow);
            aPermission = aPermission ?? string.Empty;
            // We need to get rid of possible null values
            if (FConfigData.UsePermSystem && result && aPermission.Length > 0) result = permission.UserHasPermission(aPlayer.UserIDString, aPermission);
            if (aIndReport && !result) {
                rust.SendChatMessage(aPlayer, string.Empty, lang.GetMessage("Permission Error Text", this, aPlayer.UserIDString));
                LogError(string.Format(lang.GetMessage("Permission Error Log Text", this, aPlayer.UserIDString), aPlayer.displayName, aPermission));
            }
            return result;
        }
        /// <summary>
        /// Verify if a user has the specified permission
        /// </summary>
        /// <param name="aPlayerId">The player's ID</param>
        /// <param name="aPermission">Pass <see cref="string.Empty"/> to only verify <see cref="CPermUiShow"/></param>
        /// <returns></returns>
        private bool VerifyPermission(string aPlayerId, string aPermission) {
            BasePlayer player = BasePlayer.Find(aPlayerId);
            return VerifyPermission(ref player, aPermission);
        }
        /// <summary>
        /// Retrieve server users
        /// </summary>
        /// <param name="aIndFiltered">Indicates if the output should be filtered</param>
        /// <param name="aUserId">User ID for retrieving filter text</param>
        /// <param name="aIndOffline">Retrieve the list of sleepers (offline players)</param>
        /// <returns></returns>
        private IEnumerable<BasePlayer> GetServerUserList(bool aIndFiltered, string aUserId, bool aIndOffline = false) {
            IEnumerable<BasePlayer> result;
            if (aIndOffline) {
                result = Player.Sleepers.Where(X => !X.IsNpc && !Player.IsBanned(X.userID));
            }
            else {
                result = Player.Players.Where(X => !X.IsNpc && !Player.IsBanned(X.userID));
            }
            if (aIndFiltered && FUserBtnPageSearchInputText.ContainsKey(aUserId)) result = result.Where(x => x.UserIDString.IndexOf(FUserBtnPageSearchInputText[aUserId], StringComparison.OrdinalIgnoreCase) >= 0 || x.displayName.IndexOf(FUserBtnPageSearchInputText[aUserId], StringComparison.OrdinalIgnoreCase) >= 0 );
            LogDebug("Retrieved the server user list");
            return result.OrderBy(x => x.displayName).ThenBy(x => x.userID);
        }
        /// <summary>
        /// Retrieve server users
        /// </summary>
        /// <param name="aIndFiltered">Indicates if the output should be filtered</param>
        /// <param name="aUserId">User ID for retrieving filter text</param>
        /// <returns></returns>
        private IEnumerable<ServerUsers.User> GetBannedUserList(bool aIndFiltered, string aUserId) {
            IEnumerable<ServerUsers.User> result = ServerUsers.GetAll(ServerUsers.UserGroup.Banned);
            if (aIndFiltered && FUserBtnPageSearchInputText.ContainsKey(aUserId)) result = result.Where(x => x.username.IndexOf(FUserBtnPageSearchInputText[aUserId], StringComparison.OrdinalIgnoreCase) >= 0 || x.steamid.ToString().IndexOf(FUserBtnPageSearchInputText[aUserId], StringComparison.OrdinalIgnoreCase) >= 0 );
            LogDebug("Retrieved the banned user list");
            return result.OrderBy(x => x.username).ThenBy(x => x.steamid);
        }
        /// <summary>
        /// Retrieve the target player ID from the arguments and report success
        /// </summary>
        /// <param name="aArg">Argument object</param>
        /// <param name="aTarget">Player ID</param>
        /// <returns></returns>
        private bool GetTargetFromArg(string[] aArgs, out ulong aTarget) {
            aTarget = 0;
            return aArgs.Count() > 0 && ulong.TryParse(aArgs[0], out aTarget);
        }
        /// <summary>
        /// Retrieve the target player ID and amount from the arguments and report success
        /// </summary>
        /// <param name="aArg">Argument object</param>
        /// <param name="aTarget">Player ID</param>
        /// <param name="aAmount">Amount</param>
        /// <returns></returns>
        private bool GetTargetAmountFromArg(string[] aArgs, out ulong aTarget, out float aAmount) {
            aTarget = 0;
            aAmount = 0;
            return aArgs.Count() >= 2 && ulong.TryParse(aArgs[0], out aTarget) && float.TryParse(aArgs[1], out aAmount);
        }
        /// <summary>
        /// Check if the player has the ChatMute flag set
        /// </summary>
        /// <param name="aPlayer">The player</param>
        /// <returns></returns>
        private bool GetIsMuted(ref BasePlayer aPlayer) {
            bool isServerMuted = aPlayer.HasPlayerFlag(BasePlayer.PlayerFlags.ChatMute);
            if (BetterChatMute != null) {
                return isServerMuted || (bool)BetterChatMute.Call("API_IsMuted", aPlayer.IPlayer);
            }
            else {
                return isServerMuted;
            }
        }
        /// <summary>
        /// Check if the player has the freeze.frozen permission
        /// </summary>
        /// <param name="aPlayerId">The player's ID</param>
        /// <returns></returns>
        private bool GetIsFrozen(ulong aPlayerId) => permission.UserHasPermission(aPlayerId.ToString(), CPermFreezeFrozen);
        /// <summary>
        /// Send either a kick or a ban message to Discord via the DiscordMessages plugin
        /// </summary>
        /// <param name="aAdminName">The name of the admin</param>
        /// <param name="aAdminId">The ID of the admin</param>
        /// <param name="aTargetName">The name of the target player</param>
        /// <param name="aTargetId">The ID of the target player</param>
        /// <param name="aReason">The reason message</param>
        /// <param name="aIndIsBan">If this is true a ban message is sent, else a kick message is sent</param>
        private void SendDiscordKickBanMessage(string aAdminName, string aAdminId, string aTargetName, string aTargetId, string aReason, bool aIndIsBan) {
            if (DiscordMessages != null) {
                if (CUnknownNameList.Contains(aTargetName.ToLower())) aTargetName = aTargetId;
                object fields = new[] {
                    new {
                        name = "Player", value = $"[{aTargetName}](https://steamcommunity.com/profiles/{aTargetId})", inline = true
                    }
                    , new {
                        name = aIndIsBan ? "Banned by" : "Kicked by", value = $"[{aAdminName}](https://steamcommunity.com/profiles/{aAdminId})", inline = true
                    }
                    , new {
                        name = "Reason", value = aReason, inline = false
                    }
                }
                ;
                DiscordMessages.Call("API_SendFancyMessage", aIndIsBan ? FConfigData.BanMsgWebhookUrl : FConfigData.KickMsgWebhookUrl, aIndIsBan ? "Player Ban" : "Player Kick", 3329330, JsonConvert.SerializeObject(fields) );
            }
        }
        /// <summary>
        /// Custom internal version of Assert
        /// </summary>
        /// <param name="aEval"></param>
        /// <param name="aTrueMsg"></param>
        /// <param name="aFalseMsg"></param>
        /// <returns></returns>
        private string InternalAssert(bool aEval, string aTrueMsg = "True", string aFalseMsg = "False") => aEval ? aTrueMsg : aFalseMsg;
        /// <summary>
        /// Transform a string array into a printable string./// </summary>
        /// <param name="aObj"></param>
        /// <returns></returns>
        private string StringArrToString(ref string[] aObj) => $"[ {string.Join(", ", aObj)} ]";
        /// <summary>
        /// Transform a dictionary of strings into a printable string./// </summary>
        /// <param name="aObj"></param>
        /// <returns></returns>
        private string StringDictToString(ref Dictionary<string, string> aObj) {
            StringBuilder result = new StringBuilder("{\n");
            foreach (KeyValuePair<string, string> item in aObj) {
                result.Append($"'{item.Key}': '{item.Value}'\n");
            }
            result.Append("}");
            return result.ToString();
        }
        /// <summary>
        /// Escape strings to make them usable in the UI./// </summary>
        /// <param name="aStr"></param>
        /// <returns></returns>
        private string EscapeString(string aStr) => aStr.Replace("\0", "").Replace("\a", "").Replace("\b", "").Replace("\f", "").Replace("\r", "").Replace("\n", " ").Replace("\t", " ").Replace("\v", "").Replace("\"", "ˮ").Replace("/", "∕").Replace("\\", "∖");
        /// <summary>
        /// Teleport a player to the given potition.Kindly taken from NTeleportation
        /// </summary>
        /// <param name="aPlayer">The player to teleport</param>
        /// <param name="aTarget">The target position</param>
        private void Teleport(BasePlayer aPlayer, Vector3 aTarget) {
            if (!aPlayer.IsValid() || Vector3.Distance(aTarget, default(Vector3)) < 5f) return;
            try {
                aPlayer.EnsureDismounted();
                if (aPlayer.HasParent()) {
                    aPlayer.SetParent(null, true, true);
                }
                if (aPlayer.IsConnected) {
                    aPlayer.EndLooting();
                    if (!aPlayer.IsSleeping()) {
                        Interface.CallHook("OnPlayerSleep", aPlayer);
                        aPlayer.SetPlayerFlag(BasePlayer.PlayerFlags.Sleeping, true);
                        aPlayer.sleepStartTime = Time.time;
                        BasePlayer.sleepingPlayerList.Add(aPlayer);
                        BasePlayer.bots.Remove(aPlayer);
                        aPlayer.CancelInvoke("InventoryUpdate");
                        aPlayer.CancelInvoke("TeamUpdate");
                    }
                }
                aPlayer.RemoveFromTriggers();
                // Recommended to use vanilla method due to an issue with triggers
                aPlayer.EnableServerFall(true);
                // Redundant, in OnEntityTakeDamage hook
                aPlayer.Teleport(aTarget);
                if (aPlayer.IsConnected && !Network.Net.sv.visibility.IsInside(aPlayer.net.group, aTarget)) {
                    aPlayer.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
                    aPlayer.ClientRPCPlayer(null, aPlayer, "StartLoading");
                    aPlayer.SendEntityUpdate();
                    if (!(Vanish?.Call<bool>("IsInvisible", aPlayer) ?? false))  // fix for becoming networked briefly with vanish while teleporting
                    {
                        aPlayer.UpdateNetworkGroup();
                        // Building fix
                        aPlayer.SendNetworkUpdateImmediate(false);
                    }
                }
            }
            finally {
                aPlayer.EnableServerFall(false);
                aPlayer.ForceUpdateTriggers();
                // Exploit fix for looting sleepers in safe zones
            }
        }
#endregion Utility methods
#region Upgrade methods
        /// <summary>
        /// Upgrade the config to 1.3.10 if needed
        /// </summary>
        /// <returns></returns>
        private bool UpgradeTo1310() {
            bool result = false;
            Config.Load();
            if (Config["Use Permission System"] == null) {
                FConfigData.UsePermSystem = true;
                result = true;
            }
            // Remove legacy config items
            if (Config["Enable kick action"] != null || Config["Enable ban action"] != null || Config["Enable unban action"] != null || Config["Enable kill action"] != null || Config["Enable inventory clear action"] != null || Config["Enable blueprint reset action"] != null || Config["Enable metabolism reset action"] != null || Config["Enable hurt action"] != null || Config["Enable heal action"] != null || Config["Enable mute action"] != null || Config["Enable perms action"] != null || Config["Enable freeze action"] != null ) result = true;
            Config.Clear();
            if (result) Config.WriteObject(FConfigData);
            return result;
        }
        /// <summary>
        /// Upgrade the config to 1.3.13 if needed
        /// </summary>
        /// <returns></returns>
        private bool UpgradeTo1313() {
            bool result = false;
            Config.Load();
            if (Config["Discord Webhook url for ban messages"] == null) {
                FConfigData.BanMsgWebhookUrl = string.Empty;
                result = true;
            }
            if (Config["Discord Webhook url for kick messages"] == null) {
                FConfigData.KickMsgWebhookUrl = string.Empty;
                result = true;
            }
            Config.Clear();
            if (result) Config.WriteObject(FConfigData);
            return result;
        }
        /// <summary>
        /// Upgrade the config to 1.5.6 if needed
        /// </summary>
        /// <returns></returns>
        private bool UpgradeTo156() {
            bool result = false;
            Dictionary<string, string> oldPerms = new Dictionary<string, string>() {
                {
                    "playeradministration.show", CPermUiShow
                }
                , {
                    "playeradministration.kick", CPermKick
                }
                , {
                    "playeradministration.ban", CPermBan
                }
                , {
                    "playeradministration.kill", CPermKill
                }
                , {
                    "playeradministration.perms", CPermPerms
                }
                , {
                    "playeradministration.voicemute", CPermMute
                }
                , {
                    "playeradministration.chatmute", CPermMute
                }
                , {
                    "playeradministration.freeze", CPermFreeze
                }
                , {
                    "playeradministration.clearinventory", CPermClearInventory
                }
                , {
                    "playeradministration.resetblueprint", CPermResetBP
                }
                , {
                    "playeradministration.resetmetabolism", CPermResetMetabolism
                }
                , {
                    "playeradministration.recovermetabolism", CPermRecoverMetabolism
                }
                , {
                    "playeradministration.hurt", CPermHurt
                }
                , {
                    "playeradministration.heal", CPermHeal
                }
                , {
                    "playeradministration.teleport", CPermTeleport
                }
                , {
                    "playeradministration.spectate", CPermSpectate
                }
            }
            ;
            LogDebug($"Old Perms: {StringDictToString(ref oldPerms)}");
            foreach (KeyValuePair<string, string> item in oldPerms) {
                string[] groups = permission.GetPermissionGroups(item.Key);
                LogDebug($"Groups: {StringArrToString(ref groups)}");
                string[] users = permission.GetPermissionUsers(item.Key);
                LogDebug($"Users: {StringArrToString(ref users)}");
                if (groups.Count() <= 0 && users.Count() <= 0) {
                    LogDebug("Counts are zero");
                    continue;
                }
                result = true;
                foreach (string group in groups) {
                    permission.RevokeGroupPermission(group, item.Key);
                    permission.GrantGroupPermission(group, item.Value, this);
                    LogInfo($"Fixed group permission: {group} (OLD) {item.Key} -> (NEW) {item.Value}");
                }
                foreach (string user in users) {
                    string uid = user.Substring(0, user.IndexOf('('));
                    permission.RevokeUserPermission(uid, item.Key);
                    permission.GrantUserPermission(uid, item.Value, this);
                    LogInfo($"Fixed user permission: {user} (OLD) {item.Key} -> (NEW) {item.Value}");
                }
            }
            permission.SaveData();
            return result;
        }
        /// <summary>
        /// Upgrade the config to 1.5.19 if needed
        /// </summary>
        /// <returns></returns>
        private bool UpgradeTo1519() {
            bool result = false;
            Dictionary<string, string> oldPerms = new Dictionary<string, string>() {
                {
                    "playeradministration.access.voicemute", CPermMute
                }
                , {
                    "playeradministration.access.chatmute", CPermMute
      
// ... [Code preview truncated due to length. Full source in attached file] ...

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