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

FREE RustPanel : 1.2.7 1.2.7

Нет прав для скачивания
C#:
/**
 * Changelogs:
 * 1.2.7:
 * - Global update: vk.com/@rustpanel-update
 * 1.2.6:
 * - Alerts improvements
 * - Version grabber for panel alert
 * 1.2.5:
 * - Alert supports
 * 1.2.4:
 * - Fixed troubles with team detecting
 * 1.2.3:
 * - State update on disconnected players fixes
 * 1.2.2:
 * - Supports for IP bans
 * 1.2.1:
 * - Better RaidZone support
 * 1.2.0:
 * - Support for a raid-blocks plugins
 * - Support for a IP in panel
 * 1.1.9:
 * - Fixing discord sent with double quotes
 * - Additional logs when API error
 * 1.1.8:
 * - Again trying to fix multi-calling-check-show
 * - Fixed trouble with socket silent disconnect (probably)
 * 1.1.7:
 * - Added configuration for open report panel
 * - Fixes possible socket errors
 * - Auto hide UI on plugin restart
 * - Logs for showing UI
 * 1.1.6:
 * - Changed the sign of the call for verification
 * - Added the ability to change the 'report' command in the plugin configuration
 * 1.1.5:
 * - Realized socket connection with rust panel
 * 1.1.4:
 * - Fixed stats update on high load
 * 1.1.3:
 * - Fixed state update failed
 * 1.1.2:
 * - Kick for ban fixes
 * 1.1.1:
 * - Change interface
 * 1.1.0:
 * - Possible fix state update pause...*/
// Uncommit this to add suppport for DB210
//#define DB210
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Security.Authentication;
using System.Threading;
using Facepunch;
using Facepunch.Math;
using JetBrains.Annotations;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using WebSocketSharp;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using WebSocketSharp.Net;
using Random = System.Random;
using WebSocket = WebSocketSharp.WebSocket;
namespace Oxide.Plugins {
    [Info("Rust Panel", "Hougan", "1.2.7")]
    public class RustPanel : RustPlugin {
#region Classes
        class Response {
            [JsonProperty("success")]
            public bool Success;
            [JsonProperty("data")]
            public object Data;
            public Response(bool success, object data = null) {
                this.Success = success;
                this.Data = data;
            }
        }
        /**
         * Main configuration class
         */
        private class Configuration {
            [JsonProperty("Server name for control panel")]
            public string Name;
            [JsonProperty("API URI (Do not change it!)")]
            public string ApiUri;
            [JsonProperty("SOCKET URI (Do not change it!)")]
            public string SocketUri = "wss://socket-rp5557.rustpanel.ru";
            [JsonProperty("API TOKEN (Do not change it!)")]
            public string Token;
            [JsonProperty("Unique server ID (Do not change it!)")]
            public string Hash;
            [JsonProperty("Command will open the GUI")]
            public string ChatCommand = "reports";
            [JsonProperty("Report reasons for UI")]
            public List<string> Reasons = new List<string>();
            [JsonProperty("Report cooldown (in secs)")]
            public int ReportCooldown = 1;
            [JsonProperty("Additional scan for in-game reports (F7)")]
            public bool UseF7Reports = true;
            [JsonProperty("Show moderator avatar, when message from control panel")]
            public bool ShowAvatar = true;
            [JsonProperty("Message from control panel format (Vars: %NAME% - moderator's name, %MSG% - message)")]
            public string MsgFormat = "<color=#B1D6F1>%NAME%</color>: %MSG%";
            [JsonProperty("Ban kick reason (%REASON% - ban reason, %TIME% - date of unban)")]
            public string KickFormat = "Вы забанены на этом сервере, причина: %REASON%";
            [JsonProperty("Ban broadcast (%TARGET% - target name, %REASON% - reason, you can keep empty for hide message")]
            public string BanFormat = "%TARGET% was banned for %REASON%";
            [JsonProperty("Direct message format (when moderator is chatting with suspected player)")]
            public string DirectFormat = "<color=orange>Сообщение от модератора:</color>\n%MSG%";
            public static Configuration Generate() {
                return new Configuration {
                    Name = $"Server #{Oxide.Core.Random.Range(0, 999)}", ApiUri = "https://api-rp5557.rustpanel.ru/api/plugin", SocketUri = "wss://socket-rp5557.rustpanel.ru", Token = "9accf30ad7a88ef9e7720e96df4a71a3", Hash = BatchedUpdate.Hash(), Reasons = new List<string> {
                        "Cheat", "Macros", "Bug", "1+",
                    }
                }
                ;
            }
        }
        private class API {
            public class Response {
                [JsonProperty("success")]
                public bool Success;
                [JsonProperty("data")]
                public object Data;
            }
            public class ALERT_TYPE {
                public static string SIMPLE = "simple";
                public static string STASH = "stash";
            }
            public static void Request(string module, object data, Action<Response> callback, RequestMethod method = RequestMethod.GET) {
                var payload = JsonConvert.SerializeObject(new {
                    data = data, server = ServerInfo.Get()
                }
                );
                Instance.webrequest.Enqueue($"{Settings.ApiUri}/{module}", payload, (code, response) => {
                    try {
                        var obj = JsonConvert.DeserializeObject<Response>(response);
                        callback(obj);
                    }
                    catch(Exception exc) {
                        Instance.PrintError($"Error parsing answer.{response.ToString()}");
                        callback(new Response {
                            Success = false, Data = response
                        }
                        );
                    }
                }
                , Instance, method, new Dictionary<string, string> {
                    ["Authorization"]
                    = Settings.Token, ["Content-Type"] = "application/json"
                }
                );
            }
            public static void GetBans(BasePlayer player, Action<object> callback = null) {
                Request("ban", new {
                    targetId = player.UserIDString, targetIp = player.Connection.ipaddress.Split(':')[0]
                }
                , (response) => {
                    if (response.Success) {
                        var reason = (response.Data as JObject)["reason"].ToString();
                        var time = (response.Data as JObject)["time"].ToString();
                        var isIp = (response.Data as JObject)["ip"] != null;
                        if (time.Length == 0) {
                            time = "-";
                        }
                        try {
                            player.SendConsoleCommand($"echo ID:{(response.Data as JObject)["id"].ToString()}");
                        }
                        catch {
                        }
                        player.Kick(isIp ? "Вам ограничен вход на сервер" : Settings.KickFormat.Replace("%REASON%", reason).Replace("%TIME%", time));
                        Instance.Puts($"Player {player.UserIDString} was kicked from the server, reason: {reason}");
                        callback?.Invoke(reason);
                    }
                }
                , RequestMethod.POST);
            }
            public static void SendUpdate(object data) {
                try {
                    Request("state", data, response => {
                    }
                    , RequestMethod.POST);
                }
                catch(Exception exc) {
                    Instance.PrintError($"Error while 170 {exc.ToString()}");
                }
            }
            public static void SendChat(BasePlayer player, string message) {
                Request("chat", new {
                    playerId = player.displayName, message = message
                }
                , response => {
                }
                , RequestMethod.POST);
            }
            public static void OnDisconnected(BasePlayer player, string reason) {
                Request("disconnect", new {
                    targetId = player.UserIDString, reason = reason
                }
                , response => {
                }
                , RequestMethod.POST);
            }
            public static void Report(BasePlayer player, BasePlayer target, string type, string description = null) {
                Request("report", new {
                    initiatorId = player.UserIDString, targetId = target.UserIDString, reason = type, info = description
                }
                , response => {
                }
                , RequestMethod.POST);
            }
            public static void SendAlert(string type, object obj) {
                Request("alert", new {
                    type = type, fields = obj
                }
                , response => {
                }
                , RequestMethod.POST);
            }
            public static void SendDiscord(BasePlayer player, string discord) {
                Request("discord", new {
                    discord = discord, steamId = player.UserIDString
                }
                , response => {
                    if (response.Success) {
                        Instance.Player.Message(player, Instance.lang.GetMessage("Contact.Sent", Instance, player.UserIDString) + $"<color=#8393cd> {discord}</color>", 75435345);
                        Instance.Player.Message(player, Instance.lang.GetMessage("Contact.SentWait", Instance, player.UserIDString), 75435345);
                        Instance.Puts($"Player {player.UserIDString} sent a discord for communication: {discord}");
                    }
                }
                , RequestMethod.POST);
            }
            public static void Validate() {
                Request("validate", null, response => {
                    if (!response.Success) {
                        Instance.PrintError("Can't connect to control panel");
                        Instance.PrintError($"Reason: {response.Data}");
                        Instance.PrintWarning("Check plugin configuration, and reload plugin \"o.reload RustPanel\"");
                    }
                    else {
                        Instance.Puts($"Server hash: {Settings.Hash}");
                        Instance.Puts("Connection with control panel established");
                        SocketPanel.Setup();
                        SocketPanel.DoConnect();
                        Instance.UpdateTimer = Instance.timer.Every(5 * 60, () => {
                            Instance.webrequest.Enqueue("https://cdn.rustpanel.ru/panel/plugin/check", "", (code, versionResponse) => {
                                try {
                                    var obj = JsonConvert.DeserializeObject<JObject>(versionResponse);
                                    if (obj["data"].ToString().Replace(".cs", "") != Instance.Version.ToString()) {
                                        Instance.PrintError($"Found different version from this - {obj["data"].ToString().Replace(".cs", "")}");
                                    }
                                }
                                catch(Exception exc) {
                                    Instance.PrintError("Failed to check updates for the plugin...");
                                    Instance.PrintError(exc.ToString());
                                }
                            }
                            , Instance, RequestMethod.GET);
                        }
                        );
                        Instance.UpdateTimer.Callback();
                        Instance.MainTimer = Instance.timer.Every(10, () => {
                            BatchedUpdate.Start();
                            try {
                                SocketPanel.ClientSocket.Ping();
                            }
                            catch {
                                Instance.PrintError("Failed to ping HOST.Reconnecting");
                                try {
                                    SocketPanel.ClientSocket.CloseAsync();
                                }
                                catch {
                                    SocketPanel.Setup();
                                    SocketPanel.DoConnect();
                                }
                            }
                        }
                        );
                    }
                }
                , RequestMethod.PUT);
            }
        }
#endregion
#region Classes
        private class PlayerUpdate {
            public string UserName;
            public string UserId;
            public string IP;
            public BasePlayer Player;
            public Vector3 StartPosition;
            public bool? IsRaidBlocked;
            public bool IsMoving;
            public bool InCup;
            public List<string> Team = new List<string>();
            public object Finish() {
                try {
                    if (Player == null || !Player.IsConnected) {
                        return null;
                    }
                    var plugins = new List<Plugin> {
                        Instance.NoEscape, Instance.RaidZone, Instance.RaidBlock
                    }
                    ;
                    var correct = plugins.Find(v => v != null);
                    if (correct) {
                        try {
                            switch (correct.Name) {
                                case "NoEscape" : {
                                    this.IsRaidBlocked = (bool) correct.Call("IsRaidBlocked", Player);
                                    break;
                                }
                                case "RaidZone" : {
                                    this.IsRaidBlocked = (bool) correct.Call("HasBlock", Player.userID);
                                    break;
                                }
                                case "RaidBlock" : {
                                    try {
                                        this.IsRaidBlocked = (bool) correct.Call("IsInRaid", Player);
                                    }
                                    catch {
                                        this.IsRaidBlocked = (bool) correct.Call("IsRaidBlocked", Player);
                                    }
                                    break;
                                }
                            }
                        }
                        catch {
                            Instance.PrintError($"Detected {correct.Name} plugin, but failed to call API");
                        }
                    }
                    this.IP = Player.Connection.ipaddress.Split(':')[0];
                    this.InCup = Player.IsBuildingAuthed();
                    this.IsMoving = Vector3.Distance(this.StartPosition, Player.transform.position) > 1;
                    if (Player.currentTeam != null) {
                        RelationshipManager.PlayerTeam team = RelationshipManager.Instance.FindTeam(Player.currentTeam);
                        if (team != null) {
                            team.members.ForEach((value) => {
                                if (value.ToString() != Player.UserIDString && !Team.Contains(value.ToString())) {
                                    Team.Add(value.ToString());
                                }
                            }
                            );
                        }
                    }
                    this.StartPosition = Player.transform.position;
                    var @object = new {
                        UserName = this.UserName, UserId = this.UserId, Team = this.Team, IP = this.IP, IsRaidBlocked = this.IsRaidBlocked, IsMoving = this.IsMoving, InCup = this.InCup
                    }
                    ;
                    return @object;
                }
                catch (Exception exc) {
                    return null;
                }
            }
        }
        static Random rd = new Random();
        internal static string CreateString(int stringLength) {
            const string allowedChars = "abcdefghijkmnopqrstuvwxyz0123456789";
            char[] chars = new char[stringLength];
            for (int i = 0; i < stringLength; i++) {
                chars[i] = allowedChars[rd.Next(0, allowedChars.Length)];
            }
            return new string(chars);
        }
        private class BatchedUpdate {
            public static Dictionary<ulong, double> Cooldown = new Dictionary<ulong, double>();
            public static List<PlayerUpdate> List = new List<PlayerUpdate>();
            public static string Hash() {
                return CreateString(16);
            }
            public static void Start() {
                BatchedUpdate.List = new List<PlayerUpdate>();
                BasePlayer.activePlayerList.ToList().ForEach(value => BatchedUpdate.Get(value));
                Instance.timer.Once(5, () => {
                    BatchedUpdate.SendUpdate();
                }
                );
            }
            public static void SendUpdate() {
                var objects = List.Select(v => v.Finish()).Where(v => v != null);
                var payload = new {
                    state = new {
                        players = objects
                    }
                }
                ;
                API.SendUpdate(payload);
            }
            public static PlayerUpdate Get(BasePlayer player) {
                var exists = List.Find(v => v.UserId == player.UserIDString);
                if (exists == null) {
                    List.Add(new PlayerUpdate {
                        UserName = player.displayName, UserId = player.UserIDString, StartPosition = player.transform.position.ToString().ToVector3(), Player = player
                    }
                    );
                    return BatchedUpdate.Get(player);
                }
                return exists;
            }
        }
#endregion
#region Info
        /**
         * Representing object for describe server-info
         */
        private class ServerInfo {
            [JsonProperty("name")]
            public string Name;
            [JsonProperty("hash")]
            public string Hash;
            [JsonProperty("version")]
            public string Version;
            public static ServerInfo Get() {
                return new ServerInfo {
                    Name = Settings.Name, Hash = Settings.Hash, Version = Instance.Version.ToString()
                }
                ;
            }
        }
#endregion
#region Variables
        private static RustPanel Instance;
        private static Configuration Settings = Configuration.Generate();
        // References for RB plugins to get RB status
        [PluginReference]
        private Plugin NoEscape, RaidZone, RaidBlock;
#endregion
#region Hooks
        private Timer MainTimer;
        private Timer UpdateTimer;
        private void Unload() {
            foreach (var player in BasePlayer.activePlayerList) {
                CuiHelper.DestroyUi(player, CheckLayer);
                CuiHelper.DestroyUi(player, ReportLayer);
            }
            if (UpdateTimer != null) {
                timer.Destroy(ref UpdateTimer);
            }
            if (MainTimer != null) {
                timer.Destroy(ref MainTimer);
            }
            SocketPanel.ClientSocket.Close();
        }
        // Thanks for @nimant.Without this - you would get a bug, when user has discord like "discord"#1488 <3
        private static FieldInfo hookSubscriptions = typeof(PluginManager).GetField("hookSubscriptions", (BindingFlags.Instance | BindingFlags.NonPublic));
        private void SubscribeInternalHook(string hook, string name = null) {
            var hookSubscriptions_ = hookSubscriptions.GetValue(Interface.Oxide.RootPluginManager) as IDictionary<string, IList<Plugin>>;
            IList<Plugin> plugins;
            if (!hookSubscriptions_.TryGetValue(hook, out plugins)) {
                plugins = new List<Plugin>();
                hookSubscriptions_.Add(hook, plugins);
            }
            if (string.IsNullOrEmpty(name)) {
                if (!plugins.Contains(this)) plugins.Add(this);
            }
            else {
                var plg = Interface.Oxide.RootPluginManager.GetPlugin(name);
                if (plg != null && !plugins.Contains(plg)) plugins.Add(plg);
            }
        }
        private bool IsInternal = false;
        private void OnServerInitialized() {
            Instance = this;
            API.Validate();
            try {
                //SubscribeInternalHook("IOnPlayerCommand");
                //IsInternal = true;
            }
            catch {
                PrintError("Subscribe to internal hook is unavailable, using default");
            }
            cmd.AddChatCommand(Settings.ChatCommand, this, "ChatCmdReport");
            lang.RegisterMessages(new Dictionary<string, string> {
                ["Header.Find"]
                = "FIND PLAYER", ["Header.SubDefault"] = "Who do you want to report?", ["Header.SubFindResults"] = "Here are players, which we found", ["Header.SubFindEmpty"] = "No players was found", ["Header.Search"] = "Search", ["Subject.Head"] = "Select the reason for the report", ["Subject.SubHead"] = "For player %PLAYER%", ["Cooldown"] = "Wait %TIME% sec.", ["Sent"] = "Report succesful sent", ["Contact.Error"] = "You did not sent your Discord", ["Contact.Sent"] = "You sent:", ["Contact.SentWait"] = "If you sent the correct discord - wait for a friend request.", ["Check.Text"] = "<color=#c6bdb4><size=32><b>YOU ARE CALLED FOR CHECK</b></size></color>\n<color=#958D85>You have <color=#c6bdb4><b>5 minutes</b></color> to send discord, and accept friends.\nCommand for send: <b><color=#c6bdb4>/contact</color> <<color=#c6bdb4>Nick#0000</color>></b></color>"
            }
            , this, "en");
            lang.RegisterMessages(new Dictionary<string, string> {
                ["Header.Find"]
                = "НАЙТИ ИГРОКА", ["Header.SubDefault"] = "На кого вы хотите пожаловаться?", ["Header.SubFindResults"] = "Вот игроки, которых мы нашли", ["Header.SubFindEmpty"] = "Игроки не найдены", ["Header.Search"] = "Поиск", ["Subject.Head"] = "Выберите причину репорта", ["Subject.SubHead"] = "На игрока %PLAYER%", ["Cooldown"] = "Подожди %TIME% сек.", ["Sent"] = "Жалоба успешно отправлена", ["Contact.Error"] = "Вы не отправили свой Discord", ["Contact.Sent"] = "Вы отправили:", ["Contact.SentWait"] = "<size=12>Если вы отправили корректный дискорд - ждите заявку в друзья.</size>", ["Check.Text"] = "<color=#c6bdb4><size=32><b>ВЫ ВЫЗВАНЫ НА ПРОВЕРКУ</b></size></color>\n<color=#958D85>У вас есть <color=#c6bdb4><b>5 минут</b></color> чтобы отправить дискорд и принять заявку в друзья.\nКоманда для отправки: <b><color=#c6bdb4>/contact</color> <<color=#c6bdb4>Nick#0000</color>></b></color>"
            }
            , this, "ru");
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                Settings = Config.ReadObject<Configuration>();
            }
            catch {
                PrintWarning($"Error reading config, creating one new config!");
                LoadDefaultConfig();
            }
            SaveConfig();
        }
        protected override void LoadDefaultConfig() => Settings = Configuration.Generate();
        protected override void SaveConfig() => Config.WriteObject(Settings);
        private void OnPlayerReported(BasePlayer reporter, string targetName, string targetId, string subject, string message, string type) {
            if (!Settings.UseF7Reports) {
                return;
            }
            var target = BasePlayer.Find(targetId) ?? BasePlayer.FindSleeping(targetId);
            if (target == null) {
                return;
            }
            API.Report(reporter, target, type, message);
        }
        private void OnPlayerConnected(BasePlayer player) {
            BatchedUpdate.Get(player);
            API.GetBans(player);
        }
        private void OnPlayerInit(BasePlayer player) {
            BatchedUpdate.Get(player);
            API.GetBans(player);
        }
        private void OnPlayerDisconnected(BasePlayer player, string reason) {
            API.OnDisconnected(player, reason);
        }
        void OnPlayerChat(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            var message = arg.GetString(0, "text").Trim();
            API.SendChat(player, message);
            //if (Interface.Oxide.CallHook("CanChatMessage", player, message) != null) return false;
            //return false;
        }
        private static string GridReference(Vector3 position) {
            var chars = new string[] {
                "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ"
            }
            ;
            const float block = 146;
            float size = ConVar.Server.worldsize;
            float offset = size / 2;
            float xpos = position.x + offset;
            float zpos = position.z + offset;
            int maxgrid = (int)(size / block);
            float xcoord = Mathf.Clamp(xpos / block, 0, maxgrid - 1);
            float zcoord = Mathf.Clamp(maxgrid - (zpos / block), 0, maxgrid - 1);
            string pos = string.Concat(chars[(int)xcoord], (int)zcoord);
            return (pos);
        }
        private void ProcessStash(BasePlayer player, StashContainer stash) {
            if (stash == null) {
                return;
            }
            var owner = stash.OwnerID;
            if (player.userID == stash.OwnerID) {
                return;
            }
            API.SendAlert(API.ALERT_TYPE.STASH, new {
                initiator = new {
                    value = player.UserIDString, type = "player"
                }
                , target = new {
                    value = stash.OwnerID.ToString(), type = "player"
                }
                , square = new {
                    value = $"{GridReference(player.transform.position)}", type = "text"
                }
            }
            );
        }
        private void CanSeeStash(BasePlayer player, StashContainer container) {
            ProcessStash(player, container);
        }
        private void OnStashExposed(StashContainer stash, BasePlayer player) {
            ProcessStash(player, stash);
        }
#endregion
#region External
        private void IAlert(string message) {
            API.SendAlert(API.ALERT_TYPE.SIMPLE, new {
                message = new {
                    value = message, type = "text"
                }
            }
            );
        }
        private void IReportPlayer(BasePlayer player, BasePlayer target, string type, string description = null) {
            API.Report(player, target, type, description);
        }
#endregion
#region Interfaces
        private const string CheckLayer = "RP_PrivateLayer";
        private void DrawInterface(BasePlayer player) {
            CuiElementContainer container = new CuiElementContainer();
            container.Add(new CuiButton {
                RectTransform = {
                    AnchorMin = "0.5 0.8", AnchorMax = "0.5 0.8", OffsetMin = $"-250 -50", OffsetMax = $"250 50"
                }
                , Button = {
                    Color = HexToRustFormat("#1C1C1CB6")
                }
                , Text = {
                    Text = "", Align = TextAnchor.MiddleCenter
                }
            }
            , "Under", CheckLayer);
            string text = lang.GetMessage("Check.Text", this, player.UserIDString);
            container.Add(new CuiLabel {
                RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
                }
                , Text = {
                    Text = text, Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 16
                }
            }
            , CheckLayer);
            timer.Once(2, () => {
                Puts("Destroy calling-for-check UI");
                CuiHelper.DestroyUi(player, CheckLayer);
                Puts("Showed calling-for-check UI");
                CuiHelper.AddUi(player, container);
                Effect effect = new Effect("ASSETS/BUNDLED/PREFABS/FX/INVITE_NOTICE.PREFAB".ToLower(), player, 0, new Vector3(), new Vector3());
                EffectNetwork.Send(effect, player.Connection);
            }
            );
        }
#endregion
#region Commands
        private void ChatCmdReport(BasePlayer player) {
            if (!BatchedUpdate.Cooldown.ContainsKey(player.userID)) {
                BatchedUpdate.Cooldown.Add(player.userID, 0);
            }
            if (BatchedUpdate.Cooldown[player.userID] > CurrentTime()) {
                player.Command("gametip.showtoast", 1, lang.GetMessage("Cooldown", this, player.UserIDString).Replace("%TIME%", $"{(BatchedUpdate.Cooldown[player.userID] - CurrentTime()).ToString("0")}"));
                return;
            }
            DrawReportInterface(player);
        }
        [HookMethod("IOnPlayerCommand")]
        void IOnPlayerCommand(BasePlayer player, string message) {
            if (message.Contains("/contact ")) {
                message = message.Replace("/contact", "");
            }
            else {
                return;
            }
            API.SendDiscord(player, message);
        }
        [ChatCommand("contact")]
        private void CmdChatContact(BasePlayer player, string command, string[] args) {
            if (IsInternal) {
                return;
            }
            if (args.Length == 0) {
                Player.Message(player, lang.GetMessage("Contact.Error", this, player.UserIDString), 75435345);
                return;
            }
            string result = "";
            foreach (var check in args) result += check + " ";
            API.SendDiscord(player, result);
        }
        private enum SslProtocolsHack {
            Tls = 192, Tls11 = 768, Tls12 = 3072
        }
        private static class SocketPanel {
            public static WebSocket ClientSocket = null;
            public static void Setup() {
                SocketPanel.ClientSocket = new WebSocket(Settings.SocketUri);
                ClientSocket.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
                SocketPanel.ClientSocket.SslConfiguration.CheckCertificateRevocation = false;
                ClientSocket.OnOpen += (sender, args) => {
                    Instance.Puts("Connected with control panel-socket");
                    ClientSocket.Send(JsonConvert.SerializeObject(new {
                        type = "auth", data = new {
                            type = "01", hash = Settings.Hash, name = Settings.Name, token = Settings.Token
                        }
                    }
                    ));
                }
                ;
                ClientSocket.OnMessage += (sender, args) => {
                    try {
                        var obj = JsonConvert.DeserializeObject<JObject>(args.Data);
                        object response = SocketPanel.OnMessage(obj);
                        ClientSocket.Send(JsonConvert.SerializeObject(new {
                            _id = obj["_id"].ToString(), data = new {
                                success = response != null && !(response is string), data = response
                            }
                        }
                        ));
                    }
                    catch {
                        Instance.PrintError(args.Data);
                    }
                }
                ;
                ClientSocket.OnError += (sender, args) => {
                    Instance.PrintWarning("Error from panel socket");
                }
                ;
                ClientSocket.OnClose += (sender, args) => {
                    Instance.Puts("Closed connection with panel socket");
                    Instance.Puts(JsonConvert.SerializeObject(args));
                    Instance.timer.Once(1, () => {
                        SocketPanel.Setup();
                        SocketPanel.DoConnect();
                    }
                    );
                }
                ;
            }
            public static void DoConnect() {
                ClientSocket.ConnectAsync();
            }
            public static object OnMessage(JObject obj) {
                switch (obj["type"].ToString().ToLower()) {
                    case "chat_direct" : {
                        ulong targetId = (ulong) obj["data"]["targetId"];
                        string message = obj["data"]["message"].ToString();
                        var target = BasePlayer.Find(targetId.ToString());
                        if (!target || !target.IsConnected) {
                            return "ERROR_PLAYER_OFFLINE";
                        }
                        Instance.timer.Once(1, () => {
                            target.ChatMessage(Settings.DirectFormat.Replace("%MSG%", message));
                            Effect effect = new Effect("assets/bundled/prefabs/fx/notice/item.select.fx.prefab", target, 0, new Vector3(), new Vector3());
                            EffectNetwork.Send(effect, target.Connection);
                            target.Command("gametip.showtoast", 2, "Получено сообщение от модератора, посмотрите в чат");
                        }
                        );
                        return true;
                    }
                    case "player_kick" : {
                        ulong targetId = (ulong) obj["data"]["targetId"];
                        string reason = (string) obj["data"]["reason"].ToString();
                        var target = BasePlayer.Find(targetId.ToString());
                        if (!target || !target.IsConnected) {
                            return "ERROR_PLAYER_OFFLINE";
                        }
                        Instance.timer.Once(1, () => {
                            target.Kick(reason ?? "Steam Auth Timeout");
                            Instance.Puts($"Игрок {target} был кикнут с сервера");
                        }
                        );
                        return true;
                    }
                    case "chat_send" : {
                        ulong targetId = (ulong) obj["data"]["targetId"];
                        string name = obj["data"]["name"].ToString();
                        string message = obj["data"]["message"].ToString();
                        var msg = Settings.MsgFormat.Replace("%NAME%", name).Replace("%MSG%", message);
                        foreach (var check in BasePlayer.activePlayerList) {
                            check.SendConsoleCommand("chat.add", Settings.ShowAvatar ? targetId : 0, msg);
                        }
                        return true;
                    }
                    case "check_start" : {
                        ulong targetId = (ulong) obj["data"]["targetId"];
                        var target = BasePlayer.FindByID(targetId);
                        if (target == null) {
                            return "ERROR_PLAYER_OFFLINE";
                        }
                        Instance.Puts($"Trying to show interface for {target}");
                        Instance.DrawInterface(target);
                        return true;
                    }
                    case "test" : {
                        return true;
                    }
                    case "check_stop" : {
                        ulong targetId = (ulong) obj["data"]["targetId"];
                        var target = BasePlayer.FindByID(targetId);
                        if (target == null) {
                            return "ERROR_PLAYER_OFFLINE";
                        }
                        Instance.OnPlayerConnected(target);
                        Instance.timer.Once(2, () => {
                            Instance.Puts($"Trying to hide interface for {target}");
                            CuiHelper.DestroyUi(target, CheckLayer);
                        }
                        );
                        return true;
                    }
                    case "send_ban" : {
                        ulong targetId = (ulong) obj["data"]["steamId"];
                        string targetName = (string) obj["data"]["steamName"];
                        string reason = (string) obj["data"]["reason"];
                        if (Settings.BanFormat.Length != 0) {
                            Instance.timer.Once(1, () => {
                                Instance.Server.Broadcast(Settings.BanFormat.Replace("%TARGET%", targetName).Replace("%REASON%", reason));
                            }
                            );
                        }
                        return true;
                    }
                    case "fetch_ban" : {
                        ulong targetId = (ulong) obj["data"]["targetId"];
                        var target = BasePlayer.FindByID(targetId) ?? BasePlayer.FindSleeping(targetId);
                        if (target == null) {
                            return "ERROR_PLAYER_OFFLINE";
                        }
                        API.GetBans(target, finalObj => {
                            try {
                            }
                            catch(Exception exc) {
                                Instance.PrintError(exc.ToString());
                            }
                        }
                        );
                        return true;
                    }
                    default : {
                        Instance.PrintError($"Unknown socket event: {obj["type"].ToString()}");
                        return "UNKNOWN EVENT";
                    }
                }
            }
        }
#endregion
#region Interface
        [ConsoleCommand("UI_RP_ReportPanel")]
        private void CmdConsoleReportPanel(ConsoleSystem.Arg args) {
            var player = args.Player();
            if (player == null || !args.HasArgs(1)) {
                return;
            }
            switch (args.Args[0].ToLower()) {
                case "search" : {
                    int page = args.HasArgs(2) ? int.Parse(args.Args[1]) : 0;
                    string search = args.HasArgs(3) ? args.Args[2] : "";
                    Effect effect = new Effect("assets/prefabs/tools/detonator/effects/unpress.prefab", player, 0, new Vector3(), new Vector3());
                    EffectNetwork.Send(effect, player.Connection);
                    DrawReportInterface(player, page, search, true);
                    break;
                }
                case "show" : {
                    string targetId = args.Args[1];
                    BasePlayer target = BasePlayer.Find(targetId) ?? BasePlayer.FindSleeping(targetId);
                    Effect effect = new Effect("assets/prefabs/tools/detonator/effects/unpress.prefab", player, 0, new Vector3(), new Vector3());
                    EffectNetwork.Send(effect, player.Connection);
                    CuiElementContainer container = new CuiElementContainer();
                    CuiHelper.DestroyUi(player, ReportLayer + $".T");
                    container.Add(new CuiPanel {
                        RectTransform = {
                            AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = $"{args.Args[2]} {args.Args[3]}", OffsetMax = $"{args.Args[4]} {args.Args[5]}"
                        }
                        , Image = {
                            Color = "0 0 0 1"
                        }
                    }
                    , ReportLayer + $".L", ReportLayer + $".T");
                    container.Add(new CuiButton() {
                        RectTransform = {
                            AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"-500 -500", OffsetMax = $"500 500"
                        }
                        , Button = {
                            Close = $"{ReportLayer}.T", Color = "0 0 0 1", Sprite = "assets/content/ui/ui.background.transparent.radial.psd"
                        }
                    }
                    , ReportLayer + $".T");
                    bool leftAlign = bool.Parse(args.Args[6]);
                    container.Add(new CuiButton() {
                        RectTransform = {
                            AnchorMin = $"{(leftAlign ? -1 : 2)} 0", AnchorMax = $"{(leftAlign ? -2 : 3)} 1", OffsetMin = $"-500 -500", OffsetMax = $"500 500"
                        }
                        , Button = {
                            Close = $"{ReportLayer}.T", Color = HexToRustFormat("#282828"), Sprite = "assets/content/ui/ui.background.transparent.radial.psd"
                        }
                    }
                    , ReportLayer + $".T");
                    container.Add(new CuiButton() {
                        RectTransform = {
                            AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"-1111111 -1111111", OffsetMax = $"1111111 1111111"
                        }
                        , Button = {
                            Close = $"{ReportLayer}.T", Color = "0 0 0 0.5", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                        }
                    }
                    , ReportLayer + $".T");
                    container.Add(new CuiLabel {
                        RectTransform = {
                            AnchorMin = $"{(leftAlign ? "0" : "1")} 0", AnchorMax = $"{(leftAlign ? "0" : "1")} 1", OffsetMin = $"{(leftAlign ? "-350" : "20")} 0", OffsetMax = $"{(leftAlign ? "-20" : "350")} -5"
                        }
                        , Text = {
                            FadeIn = 0.4f, Text = lang.GetMessage("Subject.Head", this, player.UserIDString), Font = "robotocondensed-bold.ttf", FontSize = 24, Align = leftAlign ? TextAnchor.UpperRight : TextAnchor.UpperLeft
                        }
                    }
                    , ReportLayer + ".T");
                    container.Add(new CuiLabel {
                        RectTransform = {
                            AnchorMin = $"{(leftAlign ? "0" : "1")} 0", AnchorMax = $"{(leftAlign ? "0" : "1")} 1", OffsetMin = $"{(leftAlign ? "-250" : "20")} 0", OffsetMax = $"{(leftAlign ? "-20" : "250")} -35"
                        }
                        , Text = {
                            FadeIn = 0.4f, Text = $"{lang.GetMessage("Subject.SubHead", this, player.UserIDString).Replace("%PLAYER%", $"<b> {
                                target.displayName
                            }
                            </b>")}", Font = "robotocondensed-regular.ttf", FontSize = 14, Color = "1 1 1 0.7", Align = leftAlign ? TextAnchor.UpperRight : TextAnchor.UpperLeft
                        }
                    }
                    , ReportLayer + ".T");
                    container.Add(new CuiElement {
                        Parent = ReportLayer + $".T", Components = {
                            new CuiRawImageComponent {
                                Png = (string) plugins.Find("ImageLibrary").Call("GetImage", target.UserIDString)
                            }
                            , new CuiRectTransformComponent {
                                AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
                            }
                        }
                    }
                    );
                    for (var i = 0; i < Settings.Reasons.Count; i++) {
                        var offXMin = (20 + (i * 5)) + i * 80;
                        var offXMax = 20 + (i * 5) + (i + 1) * 80;
                        container.Add(new CuiButton() {
                            RectTransform = {
                                AnchorMin = $"{(leftAlign ? 0 : 1)} 0", AnchorMax = $"{(leftAlign ? 0 : 1)} 0", OffsetMin = $"{(leftAlign ? -offXMax : offXMin)} 15", OffsetMax = $"{(leftAlign ? -offXMin : offXMax)} 45"
                            }
                            , Button = {
                                FadeIn = 0.4f + i * 0.2f, Color = HexToRustFormat("#FFFFFF4D"), Command = $"UI_RP_ReportPanel report {target.UserIDString} {Settings.Reasons[i].Replace(" ", "0")}"
                            }
                            , Text = {
                                FadeIn = 0.4f, Text = $"{Settings.Reasons[i]}", Align = TextAnchor.MiddleCenter, Color = "1 1 1 1", Font = "robotocondensed-regular.ttf", FontSize = 16
                            }
                        }
                        , ReportLayer + $".T");
                    }
                    CuiHelper.AddUi(player, container);
                    break;
                }
                case "report" : {
                    string targetId = args.Args[1];
                    string reason = args.Args[2].Replace("0", "");
                    BasePlayer target = BasePlayer.Find(targetId) ?? BasePlayer.FindSleeping(targetId);
                    API.Report(player, target, reason);
                    CuiHelper.DestroyUi(player, ReportLayer);
                    Effect effect = new Effect("assets/prefabs/tools/detonator/effects/unpress.prefab", player, 0, new Vector3(), new Vector3());
                    EffectNetwork.Send(effect, player.Connection);
                    player.Command("gametip.showtoast", 2, lang.GetMessage("Sent", this, player.UserIDString));
                    if (!BatchedUpdate.Cooldown.ContainsKey(player.userID)) {
                        BatchedUpdate.Cooldown.Add(player.userID, 0);
                    }
                    BatchedUpdate.Cooldown[player.userID] = CurrentTime() + Settings.ReportCooldown;
                    break;
                }
            }
        }
        private static string ReportLayer = "UI_RP_ReportPanelUI";
        private void DrawReportInterface(BasePlayer player, int page = 0, string search = "", bool redraw = false) {
            var lineAmount = 6;
            var lineMargin = 8;
            var size = (float) (700 - lineMargin * lineAmount) / lineAmount;
            var list = BasePlayer.activePlayerList.ToList();
            var finalList = list.FindAll(v => v.displayName.ToLower().Contains(search) || v.UserIDString.ToLower().Contains(search) || search == null).Skip(page * 18).Take(18);
            if (finalList.Count() == 0) {
              
// ... [Code preview truncated due to length. Full source in attached file] ...

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

Другие ресурсы пользователя 15FPS

Сверху