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

FREE RustApp : 1.6.0 1.6.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
#define RU
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Plugins;
using Oxide.Core.Plugins;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using Oxide.Core.Libraries;
using Oxide.Game.Rust.Cui;
using System.Linq;
using UnityEngine;
using Network;
using UnityEngine.Networking;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using System.IO;
using ConVar;
using Oxide.Core.Database;
using Facepunch;
using Rust;
using Steamworks;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using UnityEngine;
// Logic from DiscordSignLogger by MJSU
// https://umod.org/plugins/discord-sign-logger
using Color = System.Drawing.Color;
using Graphics = System.Drawing.Graphics;
using Apex.DataStructures;
namespace Oxide.Plugins {
    [Info("RustApp", "Hougan & Xacku & Olkuts & Frizen(adaptation)", "1.6.0devblog236")]
    public class RustApp : RustPlugin {
#region Classes
        // From RustStats by Sanlerus
        public static class EncodingBase64 {
            public static string Encode(string text) {
                var textAsBytes = Encoding.UTF8.GetBytes(text);
                return Convert.ToBase64String(textAsBytes);
            }
            public static string Decode(string encodedText) {
                var textAsBytes = Convert.FromBase64String(encodedText);
                return Encoding.UTF8.GetString(textAsBytes);
            }
        }
        // Base code idea from RustStore by Sanlerus
        public class StableRequest<T> {
            private static Dictionary<string, string> DefaultHeaders(string secret) {
                return new Dictionary<string, string> {
                    ["x-plugin-auth"]
                    = secret, ["x-plugin-version"] = _RustApp.Version.ToString(), ["x-plugin-port"] = ConVar.Server.port.ToString()
                }
                ;
            }
            private string url;
            private RequestMethod method;
            private object data;
            public Dictionary<string, string> headers = new Dictionary<string, string>();
            public Action<string> onException;
            public Action<T, string> onComplete;
            public bool debug = true;
            public bool silent = true;
            private DateTime _created = DateTime.Now;
            public StableRequest(string url, RequestMethod method, object data, string secret) {
                this.url = url;
                this.method = method;
                this.data = data;
                this.headers = DefaultHeaders(secret);
                this.onException += (a) => {
                    LastException.History.Insert(0, new LastException(url, data, a, secret));
                    if (LastException.History.Count > 10) {
                        LastException.History.RemoveRange(10, 1);
                    }
                }
                ;
            }
            public double Elapsed() {
                return (DateTime.Now - _created).TotalMilliseconds;
            }
            public void Execute(Action<T, string> onComplete, Action<string> onException) {
                if (onComplete != null) {
                    this.onComplete += onComplete;
                }
                if (onException != null) {
                    this.onException += onException;
                }
                UnityWebRequest webRequest = null;
                var body = System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data != null ? data : new {
                }
                ));
                switch (method) {
                    case RequestMethod.GET : {
                        webRequest = UnityWebRequest.Get(url);
                        break;
                    }
                    case RequestMethod.PUT : {
                        webRequest = UnityWebRequest.Put(url, "{}");
                        webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
                        webRequest.uploadHandler.contentType = "application/json";
                        break;
                    }
                    case RequestMethod.POST : {
                        webRequest = UnityWebRequest.Post(url, "{}");
                        webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
                        webRequest.uploadHandler.contentType = "application/json";
                        break;
                    }
                    case RequestMethod.DELETE : {
                        webRequest = UnityWebRequest.Delete(url);
                        webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
                        webRequest.uploadHandler.contentType = "application/json";
                        break;
                    }
                }
                if (webRequest == null) {
                    throw new Exception("bad.request.type");
                }
                if (headers != null) {
                    foreach (var chunk in headers) {
                        webRequest.SetRequestHeader(chunk.Key, chunk.Value);
                    }
                }
                webRequest.SetRequestHeader("Content-Type", "application/json");
                webRequest.timeout = 10;
                Rust.Global.Runner.StartCoroutine(this.WaitForRequest(webRequest));
            }
            private IEnumerator WaitForRequest(UnityWebRequest request) {
                yield return request.Send();
                bool isError = request.isHttpError || request.isNetworkError || request.error != null;
                var body = (request.downloadHandler?.text ?? "possible network errors, contact @rustapp_help if you see > 5 minutes").ToLower();
                if (body.Length == 0) {
                    body = "possible network errors, contact @rustapp_help if you see > 5 minutes";
                }
                if (isError) {
                    if (body.Contains("cloudflare")) {
                        onException?.Invoke("rustapp is restarting, wait please");
                    }
                    else {
                        onException?.Invoke(body);
                    }
                }
                else {
                    try {
                        if (typeof(T) == typeof(String)) {
                            onComplete?.Invoke((T)(object)request.downloadHandler?.text, request.downloadHandler?.text);
                        }
                        else {
                            var obj = JsonConvert.DeserializeObject<T>(request.downloadHandler?.text);
                            onComplete?.Invoke(obj, request.downloadHandler?.text);
                        }
                    }
                    catch (Exception parseException) {
                        var str = typeof(T).ToString();
                        _RustApp.Error($"Не удалось разобрать ответ от сервера ({request.method.ToUpper()} {request.url}): {parseException} (Response: {request.downloadHandler?.text})", $"Failed to parse server response: ({request.method.ToUpper()} {request.url}): {parseException} (Response: {request.downloadHandler?.text})" );
                    }
                }
            }
        }
        private class LastException {
            public static List<LastException> History = new List<LastException>();
            public string module;
            public string secret;
            public string payload;
            public string response;
            public DateTime time = DateTime.Now;
            public LastException(string module, object payload, string response, string secret) {
                this.module = module;
                this.secret = secret;
                this.payload = JsonConvert.SerializeObject(payload ?? "No request payload");
                this.response = response;
            }
        }
        private static class CourtUrls {
            private static string Base = "https://court.rustapp.io";
            public static string Pair = $"{CourtUrls.Base}/plugin/pair";
            public static string Validate = $"{CourtUrls.Base}/plugin/";
            public static string SendContact = $"{CourtUrls.Base}/plugin/contact";
            public static string SendState = $"{CourtUrls.Base}/plugin/state";
            public static string SendChat = $"{CourtUrls.Base}/plugin/chat";
            public static string SendAlerts = $"{CourtUrls.Base}/plugin/alerts";
            public static string SendCustomAlert = $"{CourtUrls.Base}/plugin/custom-alert";
            public static string SendReports = $"{CourtUrls.Base}/plugin/reports";
            public static string SendDestroyedSignage = $"{CourtUrls.Base}/plugin/signage";
            public static string SendSignage = $"{CourtUrls.Base}/plugin/signage";
            public static string SendWipe = $"{CourtUrls.Base}/plugin/wipe";
            public static string BanCreate = $"{CourtUrls.Base}/plugin/ban";
            public static string BanDelete = $"{CourtUrls.Base}/plugin/unban";
        }
        private static class QueueUrls {
            private static string Base = "https://queue.rustapp.io";
            public static string Fetch = $"{QueueUrls.Base}/";
            public static string Response = $"{QueueUrls.Base}/";
        }
        private static class BanUrls {
            private static string Base = "https://ban.rustapp.io";
            public static string Fetch = $"{BanUrls.Base}/plugin";
        }
        class PluginChatMessagesPayload {
            public List<PluginChatMessageEntry> messages = new List<PluginChatMessageEntry>();
        }
        public class PluginChatMessageEntry {
            public string steam_id;
            [CanBeNull]
            public string target_steam_id;
            public bool is_team;
            public string text;
        }
        class PluginReportsPayload {
            public List<PluginReportEntry> reports = new List<PluginReportEntry>();
        }
        public static class PlayerAlertType {
            public static readonly string join_with_ip_ban = "join_with_ip_ban";
            public static readonly string dug_up_stash = "dug_up_stash";
            public static readonly string custom_api = "custom_api";
        }
        public class PluginPlayerAlertEntry {
            public string type;
            public object meta;
        }
        public class PluginPlayerAlertJoinWithIpBanMeta {
            public string steam_id;
            public string ip;
            public int ban_id;
        }
        public class PluginPlayerAlertDugUpStashMeta {
            public string steam_id;
            public string owner_steam_id;
            public string position;
            public string square;
        }
        public class PluginReportEntry {
            public string initiator_steam_id;
            [CanBeNull]
            public string target_steam_id;
            public List<string> sub_targets_steam_ids;
            public string reason;
            [CanBeNull]
            public string message;
        }
        class PluginPairDto {
            [CanBeNull]
            public int ttl;
            [CanBeNull]
            public string token;
        }
        class PluginPlayerPayload {
            private static bool IsRaidBlocked(BasePlayer player) {
                if (_RustApp == null || !_RustApp.IsLoaded) {
                    return false;
                }
                var plugins = new List<Plugin> {
                    _RustApp.NoEscape, _RustApp.RaidZone, _RustApp.RaidBlock
                }
                ;
                var correct = plugins.Find(v => v != null);
                if (correct != null) {
                    try {
                        switch (correct.Name) {
                            case "NoEscape" : {
                                return (bool)correct.Call("IsRaidBlocked", player);
                            }
                            case "RaidZone" : {
                                return (bool)correct.Call("HasBlock", player.userID);
                            }
                            case "RaidBlock" : {
                                try {
                                    return (bool)correct.Call("IsInRaid", player);
                                }
                                catch {
                                    return (bool)correct.Call("IsRaidBlocked", player);
                                }
                            }
                        }
                    }
                    catch {
                        /**
                        _RustApp.Warning(
                          "Обнаружен плагин NoEscape, но не удалось вызвать API",
                          "Detected plugin NoEscape, but failed to call API"
                        );
                        */
                    }
                }
                return false;
            }
            private static bool IsBuildingAuthed(BasePlayer player) {
                var list = new List<BuildingPrivlidge>();
                Vis.Entities(player.transform.position, 16f, list, Layers.PlayerBuildings);
                return list.FirstOrDefault()?.IsAuthed(player) ?? false;
            }
            private static bool NoLicense(Network.Connection connection) {
                if (_RustApp.MultiFighting == null || !_RustApp.MultiFighting.IsLoaded) {
                    return false;
                }
                try {
                    var isSteam = (bool)_RustApp.MultiFighting.Call("IsSteam", connection);
                    return !isSteam;
                }
                catch {
                    return false;
                }
            }
            public static PluginPlayerPayload FromPlayer(BasePlayer player) {
                var payload = new PluginPlayerPayload();
                payload.position = player.transform.position.ToString();
                payload.rotation = player.eyes.rotation.ToString();
                payload.coords = GridReference(player.transform.position);
                payload.steam_id = player.UserIDString;
                payload.steam_name = player.displayName;
                payload.ip = _RustApp.IPAddressWithoutPort(player.Connection.ipaddress);
                payload.status = "active";
                payload.can_build = PluginPlayerPayload.IsBuildingAuthed(player);
                payload.is_raiding = PluginPlayerPayload.IsRaidBlocked(player);
                payload.no_license = PluginPlayerPayload.NoLicense(player.Connection);
                if (player.Team != null) {
                    payload.team = player.Team.members.Select(v => v.ToString()).Where(v => v != player.UserIDString).ToList();
                }
                return payload;
            }
            public static PluginPlayerPayload FromConnection(Network.Connection connection, string status) {
                var payload = new PluginPlayerPayload();
                payload.steam_id = connection.userid.ToString();
                payload.steam_name = connection.username;
                payload.ip = _RustApp.IPAddressWithoutPort(connection.ipaddress);
                payload.status = status;
                payload.no_license = PluginPlayerPayload.NoLicense(connection);
                var team = RelationshipManager.Instance.FindPlayersTeam(connection.userid);
                if (team != null) {
                    payload.team = team.members.Select(v => v.ToString()).Where(v => v != connection.userid.ToString()).ToList();
                }
                return payload;
            }
            public string steam_id;
            public string steam_name;
            public string ip;
            [CanBeNull]
            public string position;
            [CanBeNull]
            public string rotation;
            [CanBeNull]
            public string coords;
            public bool can_build = false;
            public bool is_raiding = false;
            public bool no_license = false;
            public string status;
            public List<string> team = new List<string>();
        }
        public class MetaInfo {
            public static MetaInfo Read() {
                if (!Interface.Oxide.DataFileSystem.ExistsDatafile("RustApp_Configuration")) {
                    return null;
                }
                return Interface.Oxide.DataFileSystem.ReadObject<MetaInfo>("RustApp_Configuration");
            }
            public static void write(MetaInfo courtMeta) {
                Interface.Oxide.DataFileSystem.WriteObject("RustApp_Configuration", courtMeta);
            }
            [JsonProperty("It is access for RustApp Court, never edit or share it")]
            public string Value;
        }
        public class CheckInfo {
            public static CheckInfo Read() {
                if (!Interface.Oxide.DataFileSystem.ExistsDatafile("RustApp_CheckMeta")) {
                    return new CheckInfo();
                }
                return Interface.Oxide.DataFileSystem.ReadObject<CheckInfo>("RustApp_CheckMeta");
            }
            public static void write(CheckInfo courtMeta) {
                // Clear checks > 30 days ago
                courtMeta.LastChecks = courtMeta.LastChecks.Where(v => _RustApp.CurrentTime() - v.Value < 30 * 24 * 60 * 60).ToDictionary(v => v.Key, v => v.Value);
                Interface.Oxide.DataFileSystem.WriteObject("RustApp_CheckMeta", courtMeta);
            }
            [JsonProperty("List of recent checks to show green-check on player")]
            public Dictionary<string, double> LastChecks = new Dictionary<string, double>();
        }
        public class PairWorker : BaseWorker {
            public string Code;
            public void EnterCode(string code) {
                @PairAssignData(code, (data) => {
                    Code = code;
                    if (data.token != null && data.token.Length > 0) {
                        Complete(data.token);
                        return;
                    }
                    Notify(data.ttl);
                    Invoke(nameof(PairWaitFinish), 1f);
                }
                , (err) => {
                    Destroy(this);
                }
                );
            }
            public void Notify(int left) {
                _RustApp.Log($"Соединение установлено, завершите подключение на сайте.", $"Connection established, complete pair on site." );
            }
            public void Complete(string token) {
                _RustApp.Log("Соединение установлено, перезагрузка...", "Connection established, reloading..." );
                if (_RustApp != null && _RustApp._Worker != null) {
                    MetaInfo.write(new MetaInfo {
                        Value = token
                    }
                    );
                    _RustApp._Worker.Awake();
                }
            }
            public void PairWaitFinish() {
                if (Code == null) {
                    Destroy(this);
                    return;
                }
                @PairAssignData(Code, (data) => {
                    if (data.token == null || data.token.Length == 0) {
                        Invoke(nameof(PairWaitFinish), 1f);
                        Notify(data.ttl);
                        return;
                    }
                    Complete(data.token);
                }
                , (err) => {
                    Invoke(nameof(PairWaitFinish), 1f);
                    Interface.Oxide.LogError($"ошибка, {err}");
                }
                );
            }
            private void @PairAssignData(string code, Action<PluginPairDto> onComplete, Action<string> onException) {
                var obj = new {
                    name = ConVar.Server.hostname, level = SteamServer.MapName ?? ConVar.Server.level, description = ConVar.Server.description + " " + ConVar.Server.motd, avatar_big = ConVar.Server.logoimage, banner_url = ConVar.Server.headerimage, online = BasePlayer.activePlayerList.Count + ServerMgr.Instance.connectionQueue.queue.Count + ServerMgr.Instance.connectionQueue.joining.Count, slots = ConVar.Server.maxplayers, port = ConVar.Server.port, branch = ConVar.Server.branch, connected = _RustApp._Worker?.Ban.IsAuthed()
                }
                ;
                Request<PluginPairDto>(CourtUrls.Pair + $"?code={code}", RequestMethod.POST, obj).Execute((data, raw) => {
                    if (data.ttl != null) {
                        data.ttl = (int)Math.Round((float)(data.ttl / 1000));
                    }
                    onComplete(data);
                }
                , (err) => {
                    if (err.Contains("code not exists")) {
                        _RustApp.Error("Ключ API более недействителен.", "API key is no longer valid." );
                        Destroy(this);
                        return;
                    }
                    onException(err);
                }
                );
            }
        }
        public class CourtWorker : BaseWorker {
            public ActionWorker Action;
            public UpdateWorker Update;
            public QueueWorker Queue;
            public PairWorker Pair;
            public BanWorker Ban;
            private MetaInfo Meta;
            public void Awake() {
                OnDestroy();
                _RustApp.Log("Добро пожаловать в RustApp! Подключение к серверам панели...", "Welcome to the RustApp! Connecting to servers..." );
                Action = gameObject.AddComponent<ActionWorker>();
                Update = gameObject.AddComponent<UpdateWorker>();
                Queue = gameObject.AddComponent<QueueWorker>();
                Ban = gameObject.AddComponent<BanWorker>();
                Meta = MetaInfo.Read();
                if (Meta != null) {
                    Connect();
                }
                else {
                    _RustApp.Warning("Ваш плагин не настроен, создайте сервер на сайте и следуйте указаниям", "Your plugin is not configured, create server on site and follow instructions" );
                }
            }
            public void Connect() {
                Auth(Meta.Value);
                @ValidateSecret(() => EnableModules(), (err) => {
                    if (err.Contains("is lower than minimal")) {
                        _RustApp.Warning($"Ваша версия плагина слишком сильно устарела, необходимо скачать новую с сайта.", $"Your version of the plugin is too outdated, you need to download a new one from the website." );
                        return;
                    }
                    if (err.Contains("Authorization secret is corrupted")) {
                        _RustApp.Warning($"Ваш ключ более недействителен.", $"Your key is no longer valid." );
                        return;
                    }
                    if (err.Contains("Check server configuration, required ip") || err.Contains("Check server configuration, required port")) {
                        _RustApp.Warning($"Конфигурация вашего сервера изменилась, необходимо переподключить сервер через сайт.", $"Your server configuration has changed, you need to reconnect the server through the site." );
                        return;
                    }
                    _RustApp.Error($"Судя по всему RustApp временно недоступен, попробуем переподключиться через 10 секунд.", $"Apparently RustApp is temporarily unavailable, let's try reconnecting in 10 seconds." );
                    Invoke(nameof(Connect), 10f);
                }
                );
            }
            public void EnableModules() {
                Action.Auth(Meta.Value);
                Update.Auth(Meta.Value);
                Queue.Auth(Meta.Value);
                Ban.Auth(Meta.Value);
                _RustApp.Log("Соединение установлено, плагин готов к работе!", "Connection established, plugin is ready!" );
                _Settings.report_ui_commands.ForEach(v => {
                    _RustApp.cmd.AddChatCommand(v, _RustApp, nameof(_RustApp.ChatCmdReport));
                }
                );
                _RustApp.cmd.AddChatCommand(_Settings.check_contact_command, _RustApp, nameof(_RustApp.CmdChatContact));
            }
            public void @ValidateSecret(Action onComplete, Action<string> onException) {
                Request<object>(CourtUrls.Validate, RequestMethod.GET).Execute((data, raw) => onComplete?.Invoke(), (err) => onException?.Invoke(err) );
            }
            public void StartPair(string code) {
                if (Pair != null) {
                    _RustApp.Warning("Вы уже подключаетесь, вы можете отменить запрос.", "You already connecting, you can reset state." );
                    return;
                }
                Pair = gameObject.AddComponent<PairWorker>();
                Pair.EnterCode(code);
            }
            public void OnDestroy() {
                if (Action != null) {
                    Destroy(Action);
                }
                if (Update != null) {
                    Destroy(Update);
                }
                if (Queue != null) {
                    Destroy(Queue);
                }
                if (Pair != null) {
                    Destroy(Pair);
                }
                if (Ban != null) {
                    Destroy(Ban);
                }
            }
        }
        public class ActionWorker : BaseWorker {
            public void @SendContact(string steam_id, string message, Action<bool> callback) {
                if (!IsReady()) {
                    return;
                }
                Request<object>(CourtUrls.SendContact, RequestMethod.POST, new {
                    steam_id, message
                }
                ).Execute((data, raw) => callback(true), (err) => callback(false) );
            }
            public void @SendWipe(Action<bool> callback) {
                if (!IsReady()) {
                    return;
                }
                Request<object>(CourtUrls.SendWipe, RequestMethod.POST).Execute((data, raw) => callback(true), (err) => callback(false) );
            }
            public void @SendBan(string steam_id, string reason, string duration, bool global, bool ban_ip) {
                if (!IsReady()) {
                    return;
                }
                Request<object>(CourtUrls.BanCreate, RequestMethod.POST, new {
                    target_steam_id = steam_id, reason = reason, global = global, ban_ip = ban_ip, duration = duration.Length > 0 ? duration : null,
                }
                ).Execute((data, raw) => {
                    _RustApp.Log($"Игрок {steam_id} заблокирован за {reason}", $"Player {steam_id} banned for {reason}" );
                    _RustApp.CloseConnection(steam_id, reason);
                }
                , (err) => _RustApp.Log($"Не удалось заблокировать {steam_id}.Причина: {err}", $"Failed to ban {steam_id}.Reason: {err}" ) );
            }
            public void @SendBanDelete(string steam_id) {
                if (!IsReady()) {
                    return;
                }
                Request<object>(CourtUrls.BanDelete, RequestMethod.POST, new {
                    target_steam_id = steam_id,
                }
                ).Execute((data, raw) => {
                    _RustApp.Log($"Игрок {steam_id} разблокирован", $"Player {steam_id} unbanned" );
                }
                , (err) => _RustApp.Log($"Не удалось разблокировать {steam_id}.Причина: {err}", $"Failed to unban {steam_id}.Reason: {err}" ) );
            }
            public void @SendCustomAlert(string message, [CanBeNull] object data) {
                if (!IsReady()) {
                    return;
                }
                Request<object>(CourtUrls.SendCustomAlert, RequestMethod.POST, new {
                    msg = message, data
                }
                ).Execute(null, (err) => {
                    _RustApp.Puts(err);
                    _RustApp.Error($"Не удалось отправить кастомное оповещение ({message})", $"Failed to send custom-alert ({message})" );
                }
                );
            }
            public void @SendSignage(BaseImageUpdate upload) {
                if (!IsReady()) {
                    return;
                }
                var obj = new {
                    steam_id = upload.PlayerId.ToString(), net_id = upload.Entity.net.ID, base64_image = Convert.ToBase64String(upload.GetImage()), type = upload.Entity.ShortPrefabName, position = upload.Entity.transform.position.ToString(), square = GridReference(upload.Entity.transform.position)
                }
                ;
                Request<string>(CourtUrls.SendSignage, RequestMethod.POST, obj).Execute((data, raw) => {
                }
                , (err) => {
                    _RustApp.Error($"Не удалось отправить табличку ({err})", $"Failed to send signage ({err})" );
                }
                );
            }
        }
        public class BanWorker : BaseWorker {
            public class BanFetchResponse {
                public List<BanFetchEntry> entries;
            }
            public class BanFetchPayload {
                public string steam_id;
                public string ip;
            }
            public class BanFetchEntry : BanFetchPayload {
                public List<BanEntry> bans;
            }
            public class BanEntry {
                public int id;
                public string steam_id;
                public string ban_ip;
                public string reason;
                public long expired_at;
                public bool ban_ip_active;
                public bool computed_is_active;
            }
            private Dictionary<string, string> PlayersCollection = new Dictionary<string, string>();
            public void Awake() {
                foreach (var player in BasePlayer.activePlayerList) {
                    FetchBan(player);
                }
                foreach (var queued in ServerMgr.Instance.connectionQueue.queue) {
                    FetchBan(queued.userid.ToString(), _RustApp.IPAddressWithoutPort(queued.ipaddress));
                }
                foreach (var loading in ServerMgr.Instance.connectionQueue.joining) {
                    FetchBan(loading.userid.ToString(), _RustApp.IPAddressWithoutPort(loading.ipaddress));
                }
            }
            protected override void OnReady() {
                InvokeRepeating(nameof(FetchBans), 0f, 2f);
            }
            public void FetchBan(BasePlayer player) {
                FetchBan(player.UserIDString, _RustApp.IPAddressWithoutPort(player.Connection.ipaddress));
            }
            public void FetchBan(string steamId, string ip) {
                // Вызов хука на возможность игнорировать проверку
                var over = Interface.Oxide.CallHook("RustApp_CanIgnoreBan", steamId);
                if (over != null) {
                    return;
                }
                if (!PlayersCollection.ContainsKey(steamId)) {
                    PlayersCollection.Add(steamId, ip);
                    return;
                }
                PlayersCollection[steamId] = ip;
            }
            private void FetchBans() {
                if (!IsReady() || PlayersCollection.Count == 0) {
                    return;
                }
                var banChecks = PlayersCollection.ToDictionary(v => v.Key, v => v.Value);
                @FetchBans(banChecks, (steamId, ban) => {
                    if (PlayersCollection.ContainsKey(steamId)) {
                        PlayersCollection.Remove(steamId);
                    }
                    if (ban != null) {
                        if (ban.steam_id == steamId) {
                            var format = ban.expired_at == 0 ? _Settings.ban_reason_format : _Settings.ban_reason_format_temporary;
                            var time = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ban.expired_at + 3 * 60 * 60 * 1000).ToString("dd.MM.yyyy HH:mm");
                            _RustApp.CloseConnection(steamId, format.Replace("%REASON%", ban.reason).Replace("%TIME%", time));
                        }
                        else {
                            _RustApp.CloseConnection(steamId, _Settings.ban_reason_ip_format);
                        }
                        CreateAlertForIpBan(ban, steamId);
                    }
                }
                , () => {
                    _RustApp.Error($"Ошибка проверки блокировок ({banChecks.Keys.Count} шт.), пытаемся снова...", $"Ban check error ({banChecks.Keys.Count} total), attempting again..." );
                    // Возвращаем неудачно отправленные сообщения обратно в массив
                    var resurrectCollection = new Dictionary<string, string>();
                    foreach (var ban in banChecks) {
                        if (resurrectCollection.ContainsKey(ban.Key)) {
                            continue;
                        }
                        resurrectCollection.Add(ban.Key, ban.Value);
                    }
                    foreach (var ban in PlayersCollection) {
                        if (resurrectCollection.ContainsKey(ban.Key)) {
                            continue;
                        }
                        resurrectCollection.Add(ban.Key, ban.Value);
                    }
                    PlayersCollection = resurrectCollection;
                }
                );
                PlayersCollection = new Dictionary<string, string>();
            }
            public void CreateAlertForIpBan(BanEntry ban, string steamId) {
                if (ban.steam_id == steamId) {
                    return;
                }
                if (!ban.ban_ip_active) {
                    return;
                }
                _RustApp._Worker.Update.SaveAlert(new PluginPlayerAlertEntry {
                    type = PlayerAlertType.join_with_ip_ban, meta = new PluginPlayerAlertJoinWithIpBanMeta {
                        steam_id = steamId, ip = ban.ban_ip, ban_id = ban.id
                    }
                }
                );
            }
            public void @FetchBans(Dictionary<string, string> entries, Action<string, BanEntry> onBan, Action onException) {
                /*
                _RustApp.Log(
                  $"Проверяем блокировки игроков ({entries.Keys.Count} шт)",
                  $"Fetch players bans ({entries.Keys.Count} pc)"
                );
                */
                var players = new List<BanFetchPayload>();
                foreach (var entry in entries) {
                    players.Add(new BanFetchPayload {
                        steam_id = entry.Key, ip = entry.Value
                    }
                    );
                }
                Request<BanFetchResponse>(BanUrls.Fetch, RequestMethod.POST, new {
                    players
                }
                ).Execute((data, raw) => {
                    foreach (var player in players) {
                        var exists = data.entries.Find(v => v.steam_id == player.steam_id);
                        if (exists == null) {
                            _RustApp.Error($"Ответ бан-сервиса не содержит запрошенного игрока: {player.steam_id}", $"The ban service response does not contain the requested player: {player.steam_id}" );
                            return;
                        }
                        var active = exists.bans.FirstOrDefault(v => v.computed_is_active);
                        onBan?.Invoke(player.steam_id, active);
                    }
                }
                , (err) => {
                    Interface.Oxide.LogWarning(err);
                    onException?.Invoke();
                }
                );
            }
        }
        public class UpdateWorker : BaseWorker {
            private List<PluginPlayerAlertEntry> PlayerAlertCollection = new List<PluginPlayerAlertEntry>();
            private List<PluginReportEntry> ReportCollection = new List<PluginReportEntry>();
            private List<PluginChatMessageEntry> ChatCollection = new List<PluginChatMessageEntry>();
            private Dictionary<string, string> DisconnectHistory = new Dictionary<string, string>();
            private Dictionary<string, string> TeamChangeHistory = new Dictionary<string, string>();
            private List<string> DestroyedSignsCollection = new List<string>();
            protected override void OnReady() {
                CancelInvoke(nameof(SendChat));
                CancelInvoke(nameof(SendUpdate));
                CancelInvoke(nameof(SendReports));
                CancelInvoke(nameof(SendAlerts));
                CancelInvoke(nameof(SendDestroyedSigns));
                InvokeRepeating(nameof(SendChat), 0, 1f);
                InvokeRepeating(nameof(SendUpdate), 0, 5f);
                InvokeRepeating(nameof(SendReports), 0, 1f);
                InvokeRepeating(nameof(SendAlerts), 0, 5f);
                InvokeRepeating(nameof(SendDestroyedSigns), 0, 5f);
            }
            public void SaveChat(PluginChatMessageEntry message) {
                ChatCollection.Add(message);
            }
            public void SaveAlert(PluginPlayerAlertEntry playerAlert) {
                PlayerAlertCollection.Add(playerAlert);
            }
            public void SaveDestroyedSign(string net_id) {
                DestroyedSignsCollection.Add(net_id);
            }
            public void SaveDisconnect(BasePlayer player, string reason) {
                if (!DisconnectHistory.ContainsKey(player.UserIDString)) {
                    DisconnectHistory.Add(player.UserIDString, reason);
                }
                DisconnectHistory[player.UserIDString] = reason;
            }
            public void SaveTeamHistory(string initiator_steam_id, string target_steam_id) {
                if (!TeamChangeHistory.ContainsKey(target_steam_id)) {
                    TeamChangeHistory.Add(target_steam_id, initiator_steam_id);
                }
                TeamChangeHistory[target_steam_id] = initiator_steam_id;
            }
            public void SaveReport(PluginReportEntry report) {
                // Вызов хука на возможность игнорировать проверку
                var over = Interface.Oxide.CallHook("RustApp_CanIgnoreReport", report.target_steam_id, report.initiator_steam_id);
                if (over != null) {
                    return;
                }
                ReportCollection.Add(report);
            }
            private void SendDestroyedSigns() {
                if (!IsReady() || DestroyedSignsCollection.Count == 0) {
                    return;
                }
                var destroyed_signs = DestroyedSignsCollection.ToList();
                Request<string>(CourtUrls.SendDestroyedSignage, RequestMethod.DELETE, new {
                    net_ids = destroyed_signs
                }
                ).Execute(null, (err) => {
                    _RustApp.Puts(err);
                    _RustApp.Error($"Не удалось отправить удаленные картинки ({destroyed_signs.Count} шт)", $"Failed to send destroyed signs ({destroyed_signs.Count} pc)" );
                    // Возвращаем неудачно отправленные сообщения обратно в массив
                    var resurrectCollection = new List<string>();
                    resurrectCollection.AddRange(destroyed_signs);
                    resurrectCollection.AddRange(DestroyedSignsCollection);
                    DestroyedSignsCollection = resurrectCollection;
                }
                );
                DestroyedSignsCollection = new List<string>();
            }
            private void SendAlerts() {
                if (!IsReady() || PlayerAlertCollection.Count == 0) {
                    return;
                }
                var alerts = PlayerAlertCollection.ToList();
                Request<object>(CourtUrls.SendAlerts, RequestMethod.POST, new {
                    alerts
                }
                ).Execute(null, (err) => {
                    _RustApp.Puts(err);
                    _RustApp.Error($"Не удалось отправить алерты ({alerts.Count} шт)", $"Failed to send alerts for player ({alerts.Count} pc)" );
                    // Возвращаем неудачно отправленные сообщения обратно в массив
                    var resurrectCollection = new List<PluginPlayerAlertEntry>();
                    resurrectCollection.AddRange(alerts);
                    resurrectCollection.AddRange(PlayerAlertCollection);
                    PlayerAlertCollection = resurrectCollection;
                }
                );
                PlayerAlertCollection = new List<PluginPlayerAlertEntry>();
            }
            private void SendChat() {
                if (!IsReady() || ChatCollection.Count == 0) {
                    return;
                }
                var messages = ChatCollection.ToList();
                Request<object>(CourtUrls.SendChat, RequestMethod.POST, new {
                    messages
                }
                ).Execute(null, (err) => {
                    _RustApp.Error($"Не удалось отправить сообщения из чата ({messages.Count} шт)", $"Failed to send messages from the chat ({messages.Count} pc)" );
                    // Возвращаем неудачно отправленные сообщения обратно в массив
                    var resurrectCollection = new List<PluginChatMessageEntry>();
                    resurrectCollection.AddRange(messages);
                    resurrectCollection.AddRange(ChatCollection);
                    ChatCollection = resurrectCollection;
                }
                );
                ChatCollection = new List<PluginChatMessageEntry>();
            }
            public void SendReports() {
                if (!IsReady() || ReportCollection.Count == 0) {
                    return;
                }
                var reports = ReportCollection.ToList();
                Request<object>(CourtUrls.SendReports, RequestMethod.POST, new {
                    reports
                }
                ).Execute(null, (err) => {
                    _RustApp.Error($"Не удалось отправить жалобы ({reports.Count} шт)", $"Failed to send messages from the chat ({reports.Count} pc)" );
                    // Возвращаем неудачно отправленные репорты обратно в массив
                    var resurrectCollection = new List<PluginReportEntry>();
                    resurrectCollection.AddRange(reports);
                    resurrectCollection.AddRange(ReportCollection);
                    ReportCollection = resurrectCollection;
                }
                );
                ReportCollection = new List<PluginReportEntry>();
            }
            public void SendUpdate() {
                if (!IsReady()) {
                    return;
                }
                var players = new List<PluginPlayerPayload>();
                foreach (var player in BasePlayer.activePlayerList) {
                    try {
                        players.Add(PluginPlayerPayload.FromPlayer(player));
                    }
                    catch (Exception exc) {
                    }
                }
                foreach (var player in ServerMgr.Instance.connectionQueue.queue) {
                    try {
                        players.Add(PluginPlayerPayload.FromConnection(player, "queued"));
                    }
                    catch (Exception exc) {
                    }
                }
                foreach (var player in ServerMgr.Instance.connectionQueue.joining) {
                    try {
                        players.Add(PluginPlayerPayload.FromConnection(player, "joining"));
                    }
                    catch (Exception exc) {
                    }
                }
                var disconnected = DisconnectHistory.ToDictionary(v => v.Key, v => v.Value);
                var team_changes = TeamChangeHistory.ToDictionary(v => v.Key, v => v.Value);
                var payload = new {
                    hostname = ConVar.Server.hostname, level = SteamServer.MapName ?? ConVar.Server.level, avatar_url = ConVar.Server.logoimage, banner_url = ConVar.Server.headerimage, slots = ConVar.Server.maxplayers, version = _RustApp.Version.ToString(), performance = _RustApp.TotalHookTime.ToString(), players, disconnected = disconnected, team_changes = team_changes
                }
                ;
                Request<object>(CourtUrls.SendState, RequestMethod.PUT, payload).Execute((data, raw) => {
                }
                , (err) => {
                    _RustApp.Error($"Не удалось отправить состояние сервера ({err})", $"Failed to send server status ({err})" );
                    /**
                        Возвращаем неудачно отправленные дисконекты
                        */
                    var resurrectCollectionDisconnects = new Dictionary<string, string>();
                    foreach (var disconnect in disconnected) {
                        if (!resurrectCollectionDisconnects.ContainsKey(disconnect.Key)) {
                            resurrectCollectionDisconnects.Add(disconnect.Key, disconnect.Value);
                        }
                    }
                    foreach (var disconnect in DisconnectHistory) {
                        if (!resurrectCollectionDisconnects.ContainsKey(disconnect.Key)) {
                            resurrectCollectionDisconnects.Add(disconnect.Key, disconnect.Value);
                        }
                    }
                    DisconnectHistory = resurrectCollectionDisconnects;
                    /**
                        Возвращаем неудачно отправленные изменения команды
                        */
                    var resurrectCollectionTeamChanges = new Dictionary<string, string>();
                    foreach (var teamChange in team_changes) {
                        if (!resurrectCollectionTeamChanges.ContainsKey(teamChange.Key)) {
                            resurrectCollectionTeamChanges.Add(teamChange.Key, teamChange.Value);
                        }
                    }
                    foreach (var teamChange in TeamChangeHistory) {
                        if (!resurrectCollectionTeamChanges.ContainsKey(teamChange.Key)) {
                            resurrectCollectionTeamChanges.Add(teamChange.Key, teamChange.Value);
                        }
                    }
                    TeamChangeHistory = resurrectCollectionTeamCha
// ... [Code preview truncated due to length. Full source in attached file] ...

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