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

FREE RustApp : 3.0.0 3.0.0

Нет прав для скачивания
C#:
// Reference: ZString
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using ConVar;
using Cysharp.Text;
using JetBrains.Annotations;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using Steamworks;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Networking;
using Color = System.Drawing.Color;
using Graphics = System.Drawing.Graphics;
using Pool = Facepunch.Pool;
using Star = ProtoBuf.PatternFirework.Star;
namespace Oxide.Plugins;
// Original ship built by Hougan.
// Planks replaced by DezLifer, Bombardir, Phrog, Nimant
// The Ship of Theseus problem: is this still his code?
[Info("RustApp", "RustApp.io", "3.0.0")]
public class RustApp : RustPlugin {
#region Variables
    // References to other plugin with API
    [PluginReference]
    private Plugin NoEscape, RaidZone, RaidBlock, MultiFighting, TGPP, ExtRaidBlock;
    private static MetaInfo _MetaInfo = MetaInfo.Read();
    private static CheckInfo _CheckInfo = CheckInfo.Read();
    private static bool _TempWipeMarker = false;
    private static RustApp _RustApp;
    private static Configuration _Settings;
    private static RustAppEngine _RustAppEngine;
    private static JsonSerializer _jsonSerializer = JsonSerializer.CreateDefault(null);
    private static (string name, string value)[] _ApiHeaders = Array.Empty<(string, string)>();
    private static readonly object _false = false;
    // avoid boxing for hooks
    private static readonly object _true = true;
    // avoid boxing for hooks
    private string _UiCommandName;
    private string _UiSearchCommand;
#endregion
#region Web API
    private static class Api {
        public static bool ErrorContains(string error, string text) {
            return error.Contains(text, StringComparison.OrdinalIgnoreCase);
        }
    }
    private static class CourtApi {
#region Shared
        public class PluginServerDto : Pool.IPooled {
            public string name;
            public string hostname;
            public string level;
            public string level_url;
            public string level_image_url;
            public int world_size;
            public string description;
            public string branch;
            public string avatar_big;
            public string avatar_url;
            public string banner_url;
            public int online;
            public int slots;
            public int reserved;
            public string version;
            public string protocol;
            public string performance;
            public int port;
            public bool connected;
            public void FillSnapshot() {
                // Static — cache all fields that do not change during plugin uptime
                name = _cachedName ??= ConVar.Server.hostname;
                hostname = _cachedHostname ??= ConVar.Server.hostname;
                level = _cachedLevel ??= (SteamServer.MapName ?? ConVar.Server.level);
                level_url = _cachedLevelUrl ??= ConVar.Server.levelurl;
                level_image_url = _cachedLevelImageUrl ??= MapUploader.ImageUrl;
                world_size = _cachedWorldSize ??= ConVar.Server.worldsize;
                description = _cachedDescription ??= (ConVar.Server.description + " " + ConVar.Server.motd);
                branch = _cachedBranch ??= ConVar.Server.branch;
                avatar_big = _cachedAvatarBig ??= ConVar.Server.logoimage;
                avatar_url = _cachedAvatarUrl ??= ConVar.Server.logoimage;
                banner_url = _cachedBannerUrl ??= ConVar.Server.headerimage;
                version = _cachedVersion ??= _RustApp.Version.ToString();
                protocol = _cachedProtocol ??= Protocol.printable.ToString();
                port = _cachedPort ??= ConVar.Server.port;
                // Dynamic — fresh value each cycle.
                online = BasePlayer.activePlayerList.Count + ServerMgr.Instance.connectionQueue.queue.Count + ServerMgr.Instance.connectionQueue.joining.Count;
                slots = ConVar.Server.maxplayers;
                reserved = ServerMgr.Instance.connectionQueue.ReservedCount;
                performance = _RustApp.TotalHookTime.ToString();
                connected = _RustAppEngine?.AuthWorker.IsAuthed ?? false;
            }
            private static string _cachedName;
            private static string _cachedHostname;
            private static string _cachedLevel;
            private static string _cachedLevelUrl;
            private static string _cachedLevelImageUrl;
            private static int? _cachedWorldSize;
            private static string _cachedDescription;
            private static string _cachedBranch;
            private static string _cachedAvatarBig;
            private static string _cachedAvatarUrl;
            private static string _cachedBannerUrl;
            private static string _cachedVersion;
            private static string _cachedProtocol;
            private static int? _cachedPort;
            public static void ResetCache() {
                _cachedName = null;
                _cachedHostname = null;
                _cachedLevel = null;
                _cachedLevelUrl = null;
                _cachedLevelImageUrl = null;
                _cachedWorldSize = null;
                _cachedDescription = null;
                _cachedBranch = null;
                _cachedAvatarBig = null;
                _cachedAvatarUrl = null;
                _cachedBannerUrl = null;
                _cachedVersion = null;
                _cachedProtocol = null;
                _cachedPort = null;
            }
            public virtual void LeavePool() {
            }
            public virtual void EnterPool() {
                name = null;
                hostname = null;
                level = null;
                level_url = null;
                level_image_url = null;
                world_size = 0;
                description = null;
                branch = null;
                avatar_big = null;
                avatar_url = null;
                banner_url = null;
                online = 0;
                slots = 0;
                reserved = 0;
                version = null;
                protocol = null;
                performance = null;
                port = 0;
                connected = false;
            }
        }
#endregion
        private const string BaseUrl = "https://court.rustapp.io";
        private const string PairUriPrefix = BaseUrl + "/plugin/pair?code=";
        private static readonly Uri UriServerInfo = new(BaseUrl + "/plugin/");
        private static readonly Uri UriState = new(BaseUrl + "/plugin/state");
        private static readonly Uri UriChat = new(BaseUrl + "/plugin/chat");
        private static readonly Uri UriReports = new(BaseUrl + "/plugin/reports");
        private static readonly Uri UriContact = new(BaseUrl + "/plugin/contact");
        private static readonly Uri UriWipe = new(BaseUrl + "/plugin/wipe");
        private static readonly Uri UriSleepingBag = new(BaseUrl + "/plugin/sleeping-bag");
        private static readonly Uri UriBan = new(BaseUrl + "/plugin/ban");
        private static readonly Uri UriUnban = new(BaseUrl + "/plugin/unban");
        private static readonly Uri UriAlerts = new(BaseUrl + "/plugin/alerts");
        private static readonly Uri UriCustomAlert = new(BaseUrl + "/plugin/custom-alert");
        private static readonly Uri UriSignage = new(BaseUrl + "/plugin/signage");
        private static readonly Uri UriKills = new(BaseUrl + "/plugin/kills");
        private static readonly Uri UriPlayerMuteGetActive = new(BaseUrl + "/plugin/player-mute/get-active");
        private static readonly Uri UriPlayerMuteCreate = new(BaseUrl + "/plugin/player-mute/mute-player");
        private static readonly Uri UriPlayerMuteDelete = new(BaseUrl + "/plugin/player-mute/unmute-player");
#region GetServerInfo
        public static StableRequest<object> GetServerInfo() {
            return new StableRequest<object>(UriServerInfo, RequestMethod.GET, null);
        }
#endregion
#region SendPairDetails
        public class PluginPairPayload : PluginServerDto {
        }
        public class PluginPairResponse {
            [CanBeNull]
            public int ttl;
            [CanBeNull]
            public string token;
        }
        public static StableRequest<PluginPairResponse> SendPairDetails(string code) {
            PluginPairPayload payload = new();
            payload.FillSnapshot();
            return new StableRequest<PluginPairResponse>(ZString.Concat(PairUriPrefix, code), RequestMethod.POST, payload);
        }
#endregion
#region StateUpdate
        public class PluginStatePlayerMetaDto {
            public readonly Dictionary<string, string> tags = new();
            public readonly Dictionary<string, string> fields = new();
        }
        public static Dictionary<ulong, PluginStatePlayerDto> players = new();
        public class PluginStatePlayerDto {
            public static PluginStatePlayerDto FromConnection(Network.Connection connection, string status) {
                var userid = connection.userid;
                if (!players.TryGetValue(userid, out var payload)) {
                    payload = new PluginStatePlayerDto();
                    players[userid] = payload;
                    payload.steam_id = connection.player is BasePlayer basePlayer ? basePlayer.UserIDString : RustApp.GetSteamIdString(userid);
                    payload.steam_name = connection.username.Replace("<blank>", "blank");
                    payload.ip = IPAddressWithoutPort(connection.ipaddress);
                    payload.no_license = DetectNoLicense(connection);
                    payload.team = Pool.Get<List<string>>();
                }
                payload.ping = Network.Net.sv.GetAveragePing(connection);
                payload.seconds_connected = (int)connection.GetSecondsConnected();
                payload.language = _RustApp.lang.GetLanguage(payload.steam_id);
                payload.status = status;
                try {
                    payload.meta = CollectPlayerMeta(payload.steam_id, payload.meta);
                }
                catch (Exception ex) {
                    Debug(ex.ToString());
                }
                payload.team ??= Pool.Get<List<string>>();
                payload.team.Clear();
                RelationshipManager.PlayerTeam? newTeam = RelationshipManager.ServerInstance.FindPlayersTeam(userid);
                if (newTeam == null) {
                    return payload;
                }
                for (int index = 0; index < newTeam.members.Count; index++) {
                    ulong member = newTeam.members[index];
                    if (member != userid) payload.team.Add(member.ToString());
                }
                return payload;
            }
            public static PluginStatePlayerDto FromPlayer(BasePlayer player) {
                PluginStatePlayerDto payload = FromConnection(player.Connection, "active");
                payload.position = player.transform.position.ToString();
                payload.rotation = player.eyes.rotation.ToString();
                payload.coords = MapHelper.PositionToString(player.transform.position);
                payload.can_build = DetectBuildingAuth(player);
                payload.is_raiding = DetectIsRaidBlock(player);
                payload.is_alive = player.IsAlive();
                return payload;
            }
            public string steam_id;
            public string steam_name;
            public string ip;
            public int ping = 0;
            public int seconds_connected;
            public string language;
            [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 bool is_alive = false;
            public string status;
            public PluginStatePlayerMetaDto meta = new();
            public List<string> team;
            public void FreePooledFields() {
                if (team != null) Pool.FreeUnmanaged(ref team);
            }
        }
        public class PluginStateUpdatePayload : PluginServerDto {
            public PluginServerDto server_info;
            public List<PluginStatePlayerDto> players;
            public Dictionary<string, string> disconnected;
            public Dictionary<string, string> team_changes;
            public override void LeavePool() {
                base.LeavePool();
                server_info = Pool.Get<PluginServerDto>();
            }
            public override void EnterPool() {
                base.EnterPool();
                if (server_info != null) Pool.Free(ref server_info);
                if (players != null) Pool.FreeUnmanaged(ref players);
                if (disconnected != null) Pool.FreeUnmanaged(ref disconnected);
                if (team_changes != null) Pool.FreeUnmanaged(ref team_changes);
            }
        }
        public static StableRequest<object> SendStateUpdate(PluginStateUpdatePayload data) {
            return new StableRequest<object>(UriState, RequestMethod.PUT, data);
        }
#endregion
#region SendChatMessages
        public class PluginChatMessageDto : Pool.IPooled {
            public string steam_id;
            public string target_steam_id;
            public bool is_team;
            public string text;
            public static PluginChatMessageDto Create(string steamId, string text, bool isTeam, [CanBeNull] string targetSteamId = null) {
                PluginChatMessageDto dto = Pool.Get<PluginChatMessageDto>();
                dto.steam_id = steamId;
                dto.target_steam_id = targetSteamId;
                dto.is_team = isTeam;
                dto.text = text;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                steam_id = null;
                target_steam_id = null;
                is_team = false;
                text = null;
            }
        }
        public class PluginChatMessagePayload : Pool.IPooled {
            public List<PluginChatMessageDto>? messages;
            public void LeavePool() => messages = Pool.Get<List<PluginChatMessageDto>>();
            public void EnterPool() {
                if (messages != null) Pool.Free(ref messages, freeElements : true);
            }
        }
        public static StableRequest<object> SendChatMessages(PluginChatMessagePayload payload) {
            return new StableRequest<object>(UriChat, RequestMethod.POST, payload);
        }
#endregion
#region SendReports
        public class PluginReportDto : Pool.IPooled {
            public string initiator_steam_id;
            public string target_steam_id;
            public List<string> sub_targets_steam_ids;
            public string reason;
            public string message;
            public static PluginReportDto Create(string initiatorSteamId, string targetSteamId, string reason, string message = null) {
                PluginReportDto? dto = Pool.Get<PluginReportDto>();
                dto.initiator_steam_id = initiatorSteamId;
                dto.target_steam_id = targetSteamId;
                dto.reason = reason;
                dto.message = message;
                return dto;
            }
            public void LeavePool() => sub_targets_steam_ids = Pool.Get<List<string>>();
            public void EnterPool() {
                initiator_steam_id = null;
                target_steam_id = null;
                reason = null;
                message = null;
                if (sub_targets_steam_ids != null) Pool.FreeUnmanaged(ref sub_targets_steam_ids);
            }
        }
        public class PluginReportBatchPayload : Pool.IPooled {
            public List<PluginReportDto>? reports;
            public void LeavePool() => reports = Pool.Get<List<PluginReportDto>>();
            public void EnterPool() {
                if (reports != null) Pool.Free(ref reports, freeElements : true);
            }
        }
        public static StableRequest<object> SendReports(PluginReportBatchPayload payload) {
            return new StableRequest<object>(UriReports, RequestMethod.POST, payload);
        }
#endregion
#region SendContact
        public static StableRequest<object> SendContact(string steamId, string contact) {
            return new StableRequest<object>(UriContact, RequestMethod.POST, new {
                steam_id = steamId, message = contact
            }
            );
        }
#endregion
#region SendWipe
        public static StableRequest<object> SendWipe() {
            return new StableRequest<object>(UriWipe, RequestMethod.POST, null);
        }
#endregion
#region Sleeping bag
        public class PluginSleepingBagDto : Pool.IPooled {
            public string initiator_steam_id;
            public string target_steam_id;
            public string position;
            public bool are_friends;
            public static PluginSleepingBagDto Create(string initiatorSteamId, string targetSteamId, string position, bool areFriends) {
                PluginSleepingBagDto? dto = Pool.Get<PluginSleepingBagDto>();
                dto.initiator_steam_id = initiatorSteamId;
                dto.target_steam_id = targetSteamId;
                dto.position = position;
                dto.are_friends = areFriends;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                initiator_steam_id = null;
                target_steam_id = null;
                position = null;
                are_friends = false;
            }
        }
        public class PluginSleepingBagBatchDto : Pool.IPooled {
            public List<PluginSleepingBagDto> sleeping_bags;
            public void LeavePool() => sleeping_bags = Pool.Get<List<PluginSleepingBagDto>>();
            public void EnterPool() {
                if (sleeping_bags != null) Pool.Free(ref sleeping_bags, freeElements : true);
            }
        }
        public static StableRequest<object> SleepingBagCreate(PluginSleepingBagBatchDto payload) {
            return new StableRequest<object>(UriSleepingBag, RequestMethod.POST, payload);
        }
#endregion
#region BanCreate
        public class PluginBanCreatePayload : Pool.IPooled {
            public string target_steam_id;
            public string reason;
            public bool global;
            public bool ban_ip;
            public string? duration;
            public string? comment;
            public static PluginBanCreatePayload Create(string targetSteamId, string reason, string? duration, bool global, bool banIp, string comment) {
                PluginBanCreatePayload? dto = Pool.Get<PluginBanCreatePayload>();
                dto.target_steam_id = targetSteamId;
                dto.reason = reason;
                dto.duration = duration;
                dto.global = global;
                dto.ban_ip = banIp;
                dto.comment = comment;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                target_steam_id = null;
                reason = null;
                duration = null;
                global = false;
                ban_ip = false;
                comment = null;
            }
        }
        public static StableRequest<object> BanCreate(PluginBanCreatePayload payload) {
            return new StableRequest<object>(UriBan, RequestMethod.POST, payload);
        }
#endregion
#region BanDelete
        public static StableRequest<object> BanDelete(string steamId) {
            return new StableRequest<object>(UriUnban, RequestMethod.POST, new {
                target_steam_id = steamId
            }
            );
        }
#endregion
#region PlayerAlert
        public static class PluginPlayerAlertType {
            public static readonly string join_with_ip_ban = "join_with_ip_ban";
            public static readonly string custom_api = "custom_api";
        }
        public class PluginPlayerAlertDto : Pool.IPooled {
            public string type;
            public object meta;
            public static PluginPlayerAlertDto Create(string type, object meta) {
                PluginPlayerAlertDto? dto = Pool.Get<PluginPlayerAlertDto>();
                dto.type = type;
                dto.meta = meta;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                type = null;
                switch (meta) {
                    case PluginPlayerAlertJoinWithIpBanMeta join : PluginPlayerAlertJoinWithIpBanMeta? j = join;
                    Pool.Free(ref j);
                    break;
                    // Add new IPooled meta types here!!
                }
                meta = null;
            }
        }
        public class PluginPlayerAlertJoinWithIpBanMeta : Pool.IPooled {
            public string steam_id;
            public string ip;
            public int ban_id;
            public static PluginPlayerAlertJoinWithIpBanMeta Create(string steamId, string ip, int banId) {
                PluginPlayerAlertJoinWithIpBanMeta? dto = Pool.Get<PluginPlayerAlertJoinWithIpBanMeta>();
                dto.steam_id = steamId;
                dto.ip = ip;
                dto.ban_id = banId;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                steam_id = null;
                ip = null;
                ban_id = 0;
            }
        }
        public class PluginPlayerAlertDugUpStashMeta {
            public string steam_id;
            public string owner_steam_id;
            public string position;
            public string square;
        }
        public class PluginPlayerAlertsBatchPayload : Pool.IPooled {
            public List<PluginPlayerAlertDto> alerts;
            public void LeavePool() => alerts = Pool.Get<List<PluginPlayerAlertDto>>();
            public void EnterPool() {
                if (alerts != null) Pool.Free(ref alerts, freeElements : true);
            }
        }
        public static StableRequest<object> CreatePlayerAlerts(PluginPlayerAlertsBatchPayload payload) {
            return new StableRequest<object>(UriAlerts, RequestMethod.POST, payload);
        }
#endregion
#region PlayerAlertCustom
        public class PluginPlayerAlertCustomDto : Pool.IPooled {
            public string msg;
            public object data;
            public string custom_icon;
            public bool hide_in_table;
            public string category;
            public List<string> custom_links;
            public static PluginPlayerAlertCustomDto Create(string msg, object? data, string? customIcon, string category, List<string>? customLinks) {
                PluginPlayerAlertCustomDto? dto = Pool.Get<PluginPlayerAlertCustomDto>();
                dto.msg = msg;
                dto.data = data;
                dto.custom_icon = customIcon;
                dto.hide_in_table = false;
                dto.category = category;
                dto.custom_links = customLinks;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                msg = null;
                data = null;
                custom_icon = null;
                hide_in_table = false;
                category = null;
                custom_links = null;
            }
        }
        public class PluginPlayerAlertCustomAlertMeta {
            public string name = "";
            public string custom_icon = null;
            public List<string> custom_links = null;
        }
        public static StableRequest<object> CreatePlayerAlertsCustom(PluginPlayerAlertCustomDto payload) {
            return new StableRequest<object>(UriCustomAlert, RequestMethod.POST, payload);
        }
#endregion
#region SendSignage
        public class PluginSignageCreateDto : Pool.IPooled {
            public string steam_id;
            public ulong net_id;
            public byte[] base64_image;
            public string type;
            public string position;
            public string square;
            public static PluginSignageCreateDto Create(string steamId, ulong netId, byte[] base64Image, string type, string position, string square) {
                PluginSignageCreateDto? dto = Pool.Get<PluginSignageCreateDto>();
                dto.steam_id = steamId;
                dto.net_id = netId;
                dto.base64_image = base64Image;
                dto.type = type;
                dto.position = position;
                dto.square = square;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                steam_id = null;
                net_id = 0;
                base64_image = null;
                type = null;
                position = null;
                square = null;
            }
        }
        public static StableRequest<object> SendSignage(PluginSignageCreateDto payload) {
            return new StableRequest<object>(UriSignage, RequestMethod.POST, payload);
        }
#endregion
#region SendSignageDestroyed
        public class SignageDestroyedDto : Pool.IPooled {
            public List<string> net_ids;
            public void LeavePool() => net_ids = Pool.Get<List<string>>();
            public void EnterPool() {
                if (net_ids != null) Pool.FreeUnmanaged(ref net_ids);
            }
        }
        public static StableRequest<object> SendSignageDestroyed(SignageDestroyedDto payload) {
            return new StableRequest<object>(UriSignage, RequestMethod.DELETE, payload);
        }
#endregion
#region SendKills
        public class PluginKillsDto : Pool.IPooled {
            public List<PluginKillEntryDto> kills;
            public void LeavePool() => kills = Pool.Get<List<PluginKillEntryDto>>();
            public void EnterPool() {
                if (kills != null) Pool.Free(ref kills, freeElements : true);
            }
        }
        public class PluginKillEntryDto : Pool.IPooled {
            public string initiator_steam_id;
            public string target_steam_id;
            public string game_time;
            public float distance;
            public string weapon;
            public bool is_headshot;
            public List<CombatLogEventDto> hit_history;
            public static PluginKillEntryDto Create(string initiatorSteamId, string targetSteamId, string gameTime, float distance, string weapon, bool isHeadshot, List<CombatLogEventDto> hitHistory) {
                PluginKillEntryDto? dto = Pool.Get<PluginKillEntryDto>();
                dto.initiator_steam_id = initiatorSteamId;
                dto.target_steam_id = targetSteamId;
                dto.game_time = gameTime;
                dto.distance = distance;
                dto.weapon = weapon;
                dto.is_headshot = isHeadshot;
                dto.hit_history = hitHistory;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                initiator_steam_id = null;
                target_steam_id = null;
                game_time = null;
                distance = 0f;
                weapon = null;
                is_headshot = false;
                if (hit_history != null) Pool.Free(ref hit_history, freeElements : true);
            }
        }
        public class CombatLogEventDto : Pool.IPooled {
            public float time;
            public string attacker_steam_id;
            public string target_steam_id;
            public string attacker;
            public string target;
            public string weapon;
            public string ammo;
            public string bone;
            public float distance;
            public float hp_old;
            public float hp_new;
            public string info;
            public int proj_hits;
            public float pi;
            public float proj_travel;
            public float pm;
            public int desync;
            public bool ad;
            public static CombatLogEventDto Create(float time, CombatLog.Event ev, Dictionary<ulong, string>? idCache = null) {
                CombatLogEventDto? dto = Pool.Get<CombatLogEventDto>();
                dto.Init(time, ev, idCache);
                return dto;
            }
            private void Init(float time, CombatLog.Event ev, Dictionary<ulong, string>? idCache) {
                if (ev.attacker is "player" or "you") attacker_steam_id = ResolveSteamId(ev.attacker_id, idCache);
                if (ev.target is "player" or "you") target_steam_id = ResolveSteamId(ev.target_id, idCache);
                this.time = time - ev.time;
                attacker = ev.attacker;
                target = ev.target;
                weapon = NormalizeName(ev.weapon);
                ammo = ev.ammo;
                bone = ev.bone;
                distance = (float)Math.Round(ev.distance, 2);
                hp_old = (float)Math.Round(ev.health_old, 2);
                hp_new = (float)Math.Round(ev.health_new, 2);
                info = ev.info;
                proj_hits = ev.proj_hits;
                proj_travel = ev.proj_travel;
                desync = ev.desync;
                pi = ev.proj_integrity;
                pm = ev.proj_mismatch;
                ad = ev.attacker_dead;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                time = 0f;
                attacker_steam_id = null;
                target_steam_id = null;
                attacker = null;
                target = null;
                weapon = null;
                ammo = null;
                bone = null;
                distance = 0f;
                hp_old = 0f;
                hp_new = 0f;
                info = null;
                proj_hits = 0;
                pi = 0f;
                proj_travel = 0f;
                pm = 0f;
                desync = 0;
                ad = false;
            }
            private static string ResolveSteamId(ulong netId, Dictionary<ulong, string>? idCache) {
                if (idCache != null && idCache.TryGetValue(netId, out string? cached)) return cached;
                string? sid = BaseNetworkable.serverEntities.TryGetEntity<BasePlayer>(new NetworkableId(netId), out BasePlayer? player) ? player.UserIDString : "";
                if (idCache != null) idCache[netId] = sid;
                return sid;
            }
            private static readonly Dictionary<string, string> _normalizedWeaponNameCache = new();
            public static void ClearCache() => _normalizedWeaponNameCache.Clear();
            private static string NormalizeName(string fullName) {
                const string Suffix = ".entity.prefab";
                if (string.IsNullOrEmpty(fullName) || fullName == "N/A" || !fullName.EndsWith(Suffix, StringComparison.Ordinal)) return fullName;
                if (_normalizedWeaponNameCache.TryGetValue(fullName, out string? normalized)) return normalized;
                int lastSlash = fullName.LastIndexOf('/');
                int start = lastSlash + 1;
                int len = fullName.Length - start - Suffix.Length;
                normalized = fullName.Substring(start, len);
                _normalizedWeaponNameCache[fullName] = normalized;
                return normalized;
            }
        }
        public static StableRequest<object> SendKills(PluginKillsDto payload) {
            return new StableRequest<object>(UriKills, RequestMethod.POST, payload);
        }
#endregion
#region PlayerMuteGetActive
        public class PlayerMuteDto {
            public string target_steam_id;
            public string reason;
            public long left_time_ms;
            public long received_at = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            private long GetExpiredAt() {
                return received_at + left_time_ms;
            }
            public string GetLeftTime() {
                long leftMs = LeftSeconds();
                if (leftMs <= 0) return RustApp._RustApp.lang.GetMessage("Time.Seconds", RustApp._RustApp, null).Replace("%COUNT%", "0");
                TimeSpan time = TimeSpan.FromMilliseconds(leftMs);
                List<string> parts = new();
                if (time.Days > 0) parts.Add(RustApp._RustApp.lang.GetMessage("Time.Days", RustApp._RustApp, null).Replace("%COUNT%", time.Days.ToString()));
                if (time.Hours > 0) parts.Add(RustApp._RustApp.lang.GetMessage("Time.Hours", RustApp._RustApp, null).Replace("%COUNT%", time.Hours.ToString()));
                if (time.Minutes > 0) parts.Add(RustApp._RustApp.lang.GetMessage("Time.Minutes", RustApp._RustApp, null).Replace("%COUNT%", time.Minutes.ToString()));
                if (time.Seconds > 0) parts.Add(RustApp._RustApp.lang.GetMessage("Time.Seconds", RustApp._RustApp, null).Replace("%COUNT%", time.Seconds.ToString()));
                return string.Join(", ", parts);
            }
            public string GetUnmuteDate() {
                DateTimeOffset date = DateTimeOffset.FromUnixTimeMilliseconds(GetExpiredAt());
                return $"{date.DateTime.ToShortDateString()} {date.DateTime.ToShortTimeString()}";
            }
            public long LeftSeconds() {
                return GetExpiredAt() - DateTimeOffset.Now.ToUnixTimeMilliseconds();
            }
        }
        public class PlayerMuteDtoIn {
            public List<PlayerMuteDto> data;
        }
        public static StableRequest<PlayerMuteDtoIn> PlayerMuteGetActive() {
            return new StableRequest<PlayerMuteDtoIn>(UriPlayerMuteGetActive, RequestMethod.GET, null);
        }
#endregion
#region PlayerMuteCreate
        public class PlayerMuteCreateDto : Pool.IPooled {
            public string target_steam_id;
            public string reason;
            public string duration;
            public bool broadcast;
            public string? comment;
            public string? references_message;
            public static PlayerMuteCreateDto Create(string targetSteamId, string reason, string duration, bool broadcast = false, string? comment = null, string? referencesMessage = null) {
                PlayerMuteCreateDto? dto = Pool.Get<PlayerMuteCreateDto>();
                dto.target_steam_id = targetSteamId;
                dto.reason = reason;
                dto.duration = duration;
                dto.broadcast = broadcast;
                dto.comment = comment;
                dto.references_message = referencesMessage;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                target_steam_id = null;
                reason = null;
                duration = null;
                broadcast = false;
                comment = null;
                references_message = null;
            }
        }
        public static StableRequest<object> PlayerMuteCreate(PlayerMuteCreateDto data) {
            return new StableRequest<object>(UriPlayerMuteCreate, RequestMethod.POST, data);
        }
#endregion
#region PlayerMuteDelete
        public class PlayerMuteDeleteDto : Pool.IPooled {
            public string target_steam_id;
            public static PlayerMuteDeleteDto Create(string targetSteamId) {
                PlayerMuteDeleteDto? dto = Pool.Get<PlayerMuteDeleteDto>();
                dto.target_steam_id = targetSteamId;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() => target_steam_id = null;
        }
        public static StableRequest<object> PlayerMuteDelete(PlayerMuteDeleteDto data) {
            return new StableRequest<object>(UriPlayerMuteDelete, RequestMethod.POST, data);
        }
#endregion
    }
    private static class QueueApi {
#region Shared
        public class QueueTaskResponse {
            public string id;
            public QueueTaskRequestConfigDto request;
        }
        public class QueueTaskRequestConfigDto {
            public string name;
            public JObject data;
        }
#endregion
        private const string BaseUrl = "https://queue.rustapp.io";
        private static readonly Uri UriQueueRoot = new(BaseUrl + "/");
#region GetQueueTasks
        public static StableRequest<List<QueueTaskResponse>> GetQueueTasks() {
            return new StableRequest<List<QueueTaskResponse>>(UriQueueRoot, RequestMethod.GET, null);
        }
#endregion
#region ProcessQueueTasks
        public class QueueTaskResponsePayload {
            public Dictionary<string, object> data;
        }
        public static StableRequest<object> ProcessQueueTasks(QueueTaskResponsePayload payload) {
            return new StableRequest<object>(UriQueueRoot, RequestMethod.PUT, payload);
        }
#endregion
    }
    private static class BanApi {
        private const string BaseUrl = "https://ban.rustapp.io";
        private static readonly Uri UriBanGetBatchV2 = new(BaseUrl + "/plugin/v2");
#region BanGetBatch
        public class BanGetBatchEntryPayloadDto : Pool.IPooled {
            public string steam_id;
            public string ip;
            public static BanGetBatchEntryPayloadDto Create(string steamId, string ip) {
                BanGetBatchEntryPayloadDto? dto = Pool.Get<BanGetBatchEntryPayloadDto>();
                dto.steam_id = steamId;
                dto.ip = ip;
                return dto;
            }
            public void LeavePool() {
            }
            public void EnterPool() {
                steam_id = null;
                ip = null;
            }
        }
        public class BanGetBatchPayload : Pool.IPooled {
            public List<BanGetBatchEntryPayloadDto> players;
            public void LeavePool() => players = Pool.Get<List<BanGetBatchEntryPayloadDto>>();
            public void EnterPool() {
                if (players != null) Pool.FreeUnmanaged(ref players);
            }
        }
        public class BanGetBatchEntryResponseDto {
            public string steam_id;
            public string ip;
            public List<BanDto> bans;
        }
        public class BanDto {
            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;
            public int sync_project_id = 0;
            public bool sync_should_kick = false;
        }
        public class BanGetBatchResponse {
            public List<BanGetBatchEntryResponseDto> entries;
        }
        public static StableRequest<BanGetBatchResponse> BanGetBatch(BanGetBatchPayload payload) {
            return new StableRequest<BanGetBatchResponse>(UriBanGetBatchV2, RequestMethod.POST, payload);
        }
#endregion
    }
#endregion
#region Configuration
    public class MetaInfo {
        public static MetaInfo Read() {
            if (!Interface.Oxide.DataFileSystem.ExistsDatafile("RustApp_Configuration")) {
                _MetaInfo = null;
                return null;
            }
            var obj = Interface.Oxide.DataFileSystem.ReadObject<MetaInfo>("RustApp_Configuration");
            _MetaInfo = obj;
            return obj;
        }
        public static void write(MetaInfo courtMeta) {
            Interface.Oxide.DataFileSystem.WriteObject("RustApp_Configuration", courtMeta);
            MetaInfo.Read();
        }
        [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) {
            const double ThirtyDaysSeconds = 30 * 24 * 60 * 60;
            double now = _RustApp.CurrentTime();
            List<string>? toRemove = Pool.Get<List<string>>();
            try {
                foreach (KeyValuePair<string, double> kv in courtMeta.LastChecks) {
                    if (now - kv.Value >= ThirtyDaysSeconds) toRemove.Add(kv.Key);
                }
                for (int i = 0; i < toRemove.Count; i++) {
                    courtMeta.LastChecks.Remove(toRemove[i]);
                }
            }
            finally {
                Pool.FreeUnmanaged(ref toRemove);
            }
            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>();
    }
    private class Configuration {
        [JsonProperty("[UI] Chat commands")]
        public List<string> report_ui_commands = new List<string>();
        [JsonProperty("[UI] Report reasons")]
        public List<string> report_ui_reasons = new List<string>();
        [JsonProperty("[UI] Cooldown between reports (seconds)")]
        public int report_ui_cooldown = 300;
        [JsonProperty("[UI] Auto-parse reports from F7 (ingame reports)")]
        public bool report_ui_auto_parse = true;
        [JsonProperty("[UI • Starter Plan] Show 'recently checked' checkbox (amount of days)")]
        public int report_ui_show_check_in = 7;
        [JsonProperty("[Chat] SteamID for message avatar (default account contains RustApp logo)")]
        public string chat_default_avatar_steamid = "76561198134964268";
        [JsonProperty("[Check] Command to send contact")]
        public string check_contact_command = "contact";
        [JsonProperty("[Components • Custom actions] Allow console command execution")]
        public bool components_custom_actions_enabled = true;
        [JsonProperty("[Components • Signages] Collect signages")]
        public bool components_signages_enabled = true;
        [JsonProperty("[Components • Kills] Collect kills")]
        public bool components_kills_enabled = true;
        [JsonProperty("[Components • Mutes] Support mutes system")]
        public bool components_mutes_enabled = true;
        public static Configuration Generate() {
            return new Configuration {
                report_ui_commands = new List<string> {
                    "report", "reports"
                }
                , report_ui_reasons = new List<string> {
                    "Cheat", "Macros", "Abuse"
                }
                , report_ui_cooldown = 300, report_ui_auto_parse = true, report_ui_show_check_in = 7, chat_default_avatar_steamid = "76561198134964268", components_custom_actions_enabled = true, components_kills_enabled = true, components_signages_enabled = true, components_mutes_enabled = true,
            }
            ;
        }
    }
#endregion
#region Workers
    private class RustAppEngine : RustAppWorker {
        public GameObject ChildObjectToWorkers;
        public AuthWorker? AuthWorker;
        public BanWorker? BanWorker;
        public StateWorker? StateWorker;
        public CheckWorker? CheckWorker;
        public QueueWorker? QueueWorker;
        public ChatWorker? ChatWorker;
        public ReportWorker? ReportWorker;
        public PlayerAlertsWorker? PlayerAlertsWorker;
        public SignageWorker? SignageWorker;
        public KillsWorker? KillsWorker;
        public PlayerMuteWorker? PlayerMuteWorker;
        public SleepingBagWorker? SleepingBagWorker;
        private new void Awake() {
            base.Awake();
            SetupAuthWorker();
        }
        public bool IsPairingNow() {
            return this.gameObject.GetComponent<PairWorker>() != null;
        }
        private void SetupAuthWorker() {
            SetupHeaders();
            AuthWorker = gameObject.AddComponent<AuthWorker>();
            AuthWorker.OnAuthSuccess += () => {
                Trace("Authed success, components enabled");
                CreateSubWorkers();
            }
            ;
            AuthWorker.OnAuthFailed += () => {
                Trace("Auth failed, components disabled");
                DestroySubWorkers();
            }
            ;
            AuthWorker.CycleAuthUpdate();
        }
        public void SetupHeaders() {
            _ApiHeaders = new[] {
                ("x-plugin-auth", _MetaInfo?.Value ?? ""), ("x-plugin-version", _RustApp.Version.ToString()), ("x-plugin-port", ConVar.Server.port.ToString()), ("Content-Type", "application/json")
            }
            ;
        }
        private void CreateSubWorkers() {
            ChildObjectToWorkers = gameObject.CreateChild();
            StateWorker = ChildObjectToWorkers.AddComponent<StateWorker>();
            CheckWorker = ChildObjectToWorkers.AddComponent<CheckWorker>();
            QueueWorker = ChildObjectToWorkers.AddComponent<QueueWorker>();
            ChatWorker = ChildObjectToWorkers.AddComponent<ChatWorker>();
            BanWorker = ChildObjectToWorkers.AddComponent<BanWorker>();
            ReportWorker = ChildObjectToWorkers.AddComponent<ReportWorker>();
            PlayerAlertsWorker = ChildObjectToWorkers.AddComponent<PlayerAlertsWorker>();
            SignageWorker = ChildObjectToWorkers.AddComponent<SignageWorker>();
            KillsWorker = ChildObjectToWorkers.AddComponent<KillsWorker>();
            PlayerMuteWorker = ChildObjectToWorkers.AddComponent<PlayerMuteWorker>();
            SleepingBagWorker = ChildObjectToWorkers.AddComponent<SleepingBagWorker>();
        }
        private void DestroySubWorkers() {
            if (ChildObjectToWorkers == null) {
                return;
            }
            Destroy(ChildObjectToWorkers);
        }
    }
    private class AuthWorker : RustAppWorker {
        public bool? IsAuthed;
        public Action? OnAuthSuccess;
        public Action? OnAuthFailed;
        private Action? _cachedAuthSuccess;
        private Action<string>? _cachedAuthError;
        public void CycleAuthUpdate() {
            InvokeRepeating(nameof(CheckAuthStatus
// ... [Code preview truncated due to length. Full source in attached file] ...

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