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

FREE RogueBotEvents : 1.0.1 1.0.1

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("RogueBot Events", "RickySpanish", "1.0.1")]
    [Description("Tracks server events for RogueBot integration")]
    public class RogueBotEvents : RustPlugin
    {
        private List<ServerEvent> _events = new List<ServerEvent>();
        private const int MAX_EVENTS = 100;
        private Timer _perfTimer;

        private class ServerEvent
        {
            public string Type;
            public string Event;
            public string Description;
            public DateTime Timestamp;
            public string Location;
            public Dictionary<string, string> Details = new Dictionary<string, string>();
        }

        private Dictionary<string, double> _lastHookTimes = new Dictionary<string, double>();
        private List<PluginPerfSnapshot> _latestPerfData = new List<PluginPerfSnapshot>();
        private float _lastSnapshotFps = 0;

        private class PluginPerfSnapshot
        {
            public string Name;
            public double HookTimeDelta;
            public double TotalHookTime;
        }

        #region Oxide Hooks

        private void Init() => LoadData();
        private void Unload()
        {
            _perfTimer?.Destroy();
            SaveData();
        }
        private void OnServerSave() { SaveData(); }

        private void OnServerInitialized()
        {
            _perfTimer = timer.Every(60f, SnapshotPluginPerformance);
        }

        [ConsoleCommand("roguebotevents")]
        private void CmdGetEvents(ConsoleSystem.Arg arg)
        {
            var activeEvents = GetActiveEvents();
            var onlinePlayers = BasePlayer.activePlayerList
                .Where(p => p != null && !string.IsNullOrEmpty(p.displayName))
                .Select(p => p.displayName).ToList();

            int limit = 30;
            if (arg.HasArgs()) int.TryParse(arg.GetString(0), out limit);

            var output = new
            {
                activeEvents = activeEvents,
                onlinePlayers = onlinePlayers,
                recentEvents = _events.Take(limit).Select(e => new
                {
                    type = e.Type,
                    evt = e.Event,
                    description = e.Description,
                    timestamp = e.Timestamp.ToString("yyyy-MM-dd HH:mm:ss"),
                    minutesAgo = (int)(DateTime.UtcNow - e.Timestamp).TotalMinutes,
                    location = e.Location,
                    details = e.Details
                })
            };

            arg.ReplyWith(JsonConvert.SerializeObject(output));
        }

        private const int MAX_ACTIVE_MINUTES = 120;

        private List<object> GetActiveEvents()
        {
            var started = new Dictionary<string, ServerEvent>();

            foreach (var evt in _events.AsEnumerable().Reverse())
            {
                if (string.IsNullOrEmpty(evt.Event)) continue;

                var key = evt.Event + (evt.Location ?? "");

                if (evt.Type == "start")
                {
                    started[key] = evt;
                }
                else if (evt.Type == "end")
                {
                    if (!string.IsNullOrEmpty(evt.Location))
                    {
                        started.Remove(key);
                    }
                    else
                    {
                        var toRemove = started.Keys.Where(k => k.StartsWith(evt.Event)).ToList();
                        foreach (var k in toRemove)
                            started.Remove(k);
                    }
                }
            }

            var now = DateTime.UtcNow;
            return started.Values
                .Where(e => (now - e.Timestamp).TotalMinutes < MAX_ACTIVE_MINUTES)
                .Select(e => new
                {
                    name = e.Event,
                    description = e.Description,
                    location = e.Location,
                    minutesAgo = (int)(now - e.Timestamp).TotalMinutes
                }).Cast<object>().ToList();
        }

        #endregion

        #region Event Logging - Simple start/end pattern

        private void LogStart(string eventName, string description, string location = null, Dictionary<string, string> details = null)
        {
            _events.Insert(0, new ServerEvent
            {
                Type = "start",
                Event = eventName,
                Description = description,
                Location = location,
                Timestamp = DateTime.UtcNow,
                Details = details ?? new Dictionary<string, string>()
            });
            TrimEvents();
        }

        private void LogEnd(string eventName, string description, string location = null, Dictionary<string, string> details = null)
        {
            _events.Insert(0, new ServerEvent
            {
                Type = "end",
                Event = eventName,
                Description = description,
                Location = location,
                Timestamp = DateTime.UtcNow,
                Details = details ?? new Dictionary<string, string>()
            });
            TrimEvents();
        }

        private void LogEvent(string type, string description, Dictionary<string, string> details = null)
        {
            _events.Insert(0, new ServerEvent
            {
                Type = type,
                Description = description,
                Timestamp = DateTime.UtcNow,
                Details = details ?? new Dictionary<string, string>()
            });
            TrimEvents();
        }

        private void TrimEvents()
        {
            while (_events.Count > MAX_EVENTS)
                _events.RemoveAt(_events.Count - 1);
        }

        #endregion

        #region Player Events

        private void OnPlayerConnected(BasePlayer player)
        {
            if (player == null) return;
            LogEvent("player_join", $"{player.displayName} joined", new Dictionary<string, string>
            {
                ["player"] = player.displayName
            });
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player == null) return;
            LogEvent("player_leave", $"{player.displayName} left", new Dictionary<string, string>
            {
                ["player"] = player.displayName,
                ["reason"] = reason ?? "Disconnected"
            });
        }

        private void OnPlayerDeath(BasePlayer player, HitInfo info)
        {
            if (player == null || player.IsNpc) return;

            string killer = "Unknown";
            string weapon = "Unknown";
            string deathType = "death";
            string description;

            if (info != null)
            {
                var attacker = info.InitiatorPlayer;

                if (attacker != null && attacker != player)
                {
                    killer = attacker.displayName;
                    deathType = "pvp_kill";
                }
                else if (attacker != null && attacker == player)
                {
                    killer = "Self";
                    deathType = "suicide";
                }
                else if (info.Initiator != null)
                {
                    killer = info.Initiator.ShortPrefabName ?? "Environment";
                    deathType = "pve_death";
                }

                weapon = info.Weapon?.GetItem()?.info?.displayName?.english
                    ?? info.WeaponPrefab?.ShortPrefabName ?? "Unknown";
            }

            if (deathType == "pvp_kill")
                description = $"{killer} killed {player.displayName} with {weapon}";
            else if (deathType == "suicide")
                description = $"{player.displayName} killed themselves with {weapon}";
            else
                description = $"{player.displayName} died to {killer}";

            LogEvent(deathType, description, new Dictionary<string, string>
            {
                ["victim"] = player.displayName,
                ["killer"] = killer,
                ["weapon"] = weapon,
                ["location"] = GetGrid(player.transform.position)
            });
        }

        #endregion

        #region Vanilla Events

        private Dictionary<string, DateTime> _lastLogged = new Dictionary<string, DateTime>();

        private bool ShouldLog(string eventName)
        {
            if (_lastLogged.TryGetValue(eventName, out var last) && (DateTime.UtcNow - last).TotalSeconds < 60)
                return false;
            _lastLogged[eventName] = DateTime.UtcNow;
            return true;
        }

        private void OnEntitySpawned(BaseNetworkable entity)
        {
            if (entity == null) return;

            if (entity is PatrolHelicopter && ShouldLog("heli_start"))
                LogStart("Patrol Helicopter", "Patrol Helicopter spawned");
            else if (entity is CargoShip && ShouldLog("cargo_start"))
                LogStart("Cargo Ship", "Cargo Ship spawned");
            else if (entity is CH47Helicopter && ShouldLog("chinook_start"))
                LogStart("Chinook", "Chinook spawned");
            else if (entity is CargoPlane && ShouldLog("plane_start"))
                LogStart("Cargo Plane", "Airdrop incoming");
        }

        private void OnEntityKill(BaseNetworkable entity)
        {
            if (entity == null) return;

            if (entity is PatrolHelicopter && ShouldLog("heli_end"))
                LogEnd("Patrol Helicopter", "Patrol Helicopter destroyed");
            else if (entity is CargoShip && ShouldLog("cargo_end"))
                LogEnd("Cargo Ship", "Cargo Ship left");
            else if (entity is CH47Helicopter && ShouldLog("chinook_end"))
                LogEnd("Chinook", "Chinook left");
        }

        #endregion

        #region Custom Plugin Events

        void OnConvoyStart() { LogStart("Convoy", "Convoy started"); }
        void OnConvoyStop() { LogEnd("Convoy", "Convoy ended"); }

        void OnArmoredTrainEventStart() { LogStart("Armored Train", "Armored Train started"); }
        void OnArmoredTrainEventStop() { LogEnd("Armored Train", "Armored Train ended"); }

        void OnTrainEventStarted(TrainEngine t) { LogStart("Cargo Train", "Cargo Train started"); }
        void OnTrainEventEnded(TrainEngine t) { LogEnd("Cargo Train", "Cargo Train ended"); }

        void OnHarborEventStart() { LogStart("Harbor Event", "Harbor Event started"); }
        void OnHarborEventEnd(HashSet<BaseEntity> e) { LogEnd("Harbor Event", "Harbor Event ended"); }

        void OnJunkyardEventStart() { LogStart("Junkyard Event", "Junkyard Event started"); }
        void OnJunkyardEventEnd(HashSet<BaseEntity> e) { LogEnd("Junkyard Event", "Junkyard Event ended"); }

        void OnPowerPlantEventStart() { LogStart("Power Plant Event", "Power Plant Event started"); }
        void OnPowerPlantEventEnd(HashSet<BaseEntity> e) { LogEnd("Power Plant Event", "Power Plant Event ended"); }

        void OnSatDishEventStart() { LogStart("Satellite Dish Event", "Satellite Dish Event started"); }
        void OnSatDishEventEnd(HashSet<BaseEntity> e) { LogEnd("Satellite Dish Event", "Satellite Dish Event ended"); }

        void OnSputnikEventStart() { LogStart("Sputnik Event", "Sputnik Event started"); }
        void OnSputnikEventStop() { LogEnd("Sputnik Event", "Sputnik Event ended"); }

        void OnWaterEventStart() { LogStart("Water Event", "Water Event started"); }
        void OnWaterEventEnd(HashSet<BaseEntity> e) { LogEnd("Water Event", "Water Event ended"); }

        void OnAirEventStart(HashSet<BaseEntity> e) { LogStart("Air Event", "Air Event started"); }
        void OnAirEventEnd(HashSet<BaseEntity> e) { LogEnd("Air Event", "Air Event ended"); }

        void OnGasStationEventStart(Vector3 pos, float radius) { LogStart("Gas Station Event", $"Gas Station Event started at {GetGrid(pos)}", GetGrid(pos)); }
        void OnGasStationEventEnd() { LogEnd("Gas Station Event", "Gas Station Event ended"); }

        void OnFerryTerminalEventStart(Vector3 pos, float radius) { LogStart("Ferry Terminal Event", "Ferry Terminal Event started"); }
        void OnFerryTerminalEventEnd() { LogEnd("Ferry Terminal Event", "Ferry Terminal Event ended"); }

        void OnOperationFortressStart() { LogStart("Operation Fortress", "Operation Fortress started"); }
        void OnOperationFortressStop() { LogEnd("Operation Fortress", "Operation Fortress ended"); }

        void OnCaravanStart() { LogStart("Caravan", "Caravan spawned"); }
        void OnCaravanStop() { LogEnd("Caravan", "Caravan ended"); }
        void OnCaravanStartMoving(Vector3 position) { LogStart("Caravan Moving", $"Caravan moving at {GetGrid(position)}", GetGrid(position)); }
        void OnCaravanStopMoving(Vector3 position) { LogEnd("Caravan Moving", $"Caravan stopped at {GetGrid(position)}"); }

        void OnRaidableBaseStarted(Vector3 pos, int diff)
        {
            string d = diff == 0 ? "Easy" : diff == 1 ? "Medium" : diff == 2 ? "Hard" : "Expert";
            string grid = GetGrid(pos);
            LogStart($"Raidable Base", $"{d} Raidable Base at {grid}", grid, new Dictionary<string, string> { ["difficulty"] = d });
        }

        void OnRaidableBaseEnded(Vector3 pos, int diff)
        {
            string d = diff == 0 ? "Easy" : diff == 1 ? "Medium" : diff == 2 ? "Hard" : "Expert";
            string grid = GetGrid(pos);
            LogEnd($"Raidable Base", $"{d} Raidable Base completed at {grid}", grid);
        }

        #endregion

        #region Performance Monitoring

        private void SnapshotPluginPerformance()
        {
            try
            {
                _lastSnapshotFps = Performance.current.frameRate;
                var currentPlugins = new HashSet<string>();
                var snapshots = new List<PluginPerfSnapshot>();

                foreach (var plugin in Interface.Oxide.RootPluginManager.GetPlugins())
                {
                    if (plugin == null) continue;
                    string name = plugin.Title ?? plugin.Name ?? "Unknown";
                    currentPlugins.Add(name);

                    double hookTime = 0;
#if CARBON
                    try { hookTime = plugin.TotalHookTime.TotalMilliseconds; }
#else
                    try { hookTime = plugin.TotalHookTime; }
#endif
                    catch { continue; }

                    double delta = 0;
                    if (_lastHookTimes.TryGetValue(name, out var prev))
                    {
                        delta = hookTime - prev;
                        if (delta < 0) delta = hookTime;
                    }
                    _lastHookTimes[name] = hookTime;

                    if (delta > 0.001)
                    {
                        snapshots.Add(new PluginPerfSnapshot
                        {
                            Name = name,
                            HookTimeDelta = delta,
                            TotalHookTime = hookTime
                        });
                    }
                }

                var toRemove = _lastHookTimes.Keys.Where(k => !currentPlugins.Contains(k)).ToList();
                foreach (var key in toRemove) _lastHookTimes.Remove(key);

                snapshots.Sort((a, b) => b.HookTimeDelta.CompareTo(a.HookTimeDelta));
                _latestPerfData = snapshots;
            }
            catch (Exception ex)
            {
                Puts($"[Perf] Error: {ex.Message}");
            }
        }

        [ConsoleCommand("roguebotperf")]
        private void CmdGetPerf(ConsoleSystem.Arg arg)
        {
            var top = _latestPerfData.Take(15).Select(p => new
            {
                name = p.Name,
                hookTime60s = Math.Round(p.HookTimeDelta, 4),
                totalHookTime = Math.Round(p.TotalHookTime, 2)
            });

            var output = new
            {
                fps = Math.Round(_lastSnapshotFps, 1),
                entityCount = BaseNetworkable.serverEntities?.Count ?? 0,
                memoryMB = Math.Round(System.GC.GetTotalMemory(false) / 1048576.0, 1),
                pluginCount = Interface.Oxide.RootPluginManager.GetPlugins().Count(),
                topPlugins = top,
                timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")
            };

            arg.ReplyWith(JsonConvert.SerializeObject(output));
        }

        #endregion

        #region Helpers

        private string GetGrid(Vector3 pos) => MapHelper.PositionToString(pos);

        private void LoadData()
        {
            _events = Interface.Oxide.DataFileSystem.ReadObject<List<ServerEvent>>("RogueBotEvents") ?? new List<ServerEvent>();
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("RogueBotEvents", _events);
        }

        #endregion
    }
}

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