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

FREE BattleReplay : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("BattleReplay", "yougame.biz "1.3.0")]
    [Description("Automatic recording based on conditions, excluding teammates and checking weapon possession with performance optimization and manual trigger options.")]
    internal class BattleReplay : RustPlugin
    {
        #region Configuration
        private static ConfigData config = new ConfigData();

        private class ConfigData
        {
            [JsonProperty(PropertyName = "Check Interval (seconds)")]
            public float checkInterval = 5f;

            [JsonProperty(PropertyName = "Recording Distance (meters)")]
            public float recordingDistance = 50f;

            [JsonProperty(PropertyName = "Region Size (meters)")]
            public float regionSize = 100f;

            [JsonProperty(PropertyName = "Recording Cooldown (seconds)")]
            public float recordingCooldown = 60f;

            [JsonProperty(PropertyName = "Auto Recording Length (minutes)")]
            public int autoRecordingLength = 1;

            [JsonProperty(PropertyName = "Skip Admins")]
            public bool skipAdmin = true;

            [JsonProperty(PropertyName = "Total Recorded Logs")]
            public int totalRecordedLogs = 0;

            [JsonProperty(PropertyName = "Total Uploaded Logs")]
            public int totalUploadedLogs = 0;

            [JsonProperty(PropertyName = "Max Replay Recordings Per Player")]
            public int maxReplayRecordings = 3;

            [JsonProperty(PropertyName = "Replay Recording Duration (minutes)")]
            public int replayDuration = 5;

            // Discord Configuration
            [JsonProperty(PropertyName = "Discord Webhook URL")]
            public string discordWebhookUrl = "https://discord.com/api/webhooks/your-webhook-url";

            [JsonProperty(PropertyName = "Discord Notification for Recording Start")]
            public bool discordNotifyRecordingStart = true;

            [JsonProperty(PropertyName = "Discord Notification for Recording Stop")]
            public bool discordNotifyRecordingStop = true;

            [JsonProperty(PropertyName = "Discord Message Color")]
            public int discordMessageColor = 39423;
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<ConfigData>();
                if (config == null) LoadDefaultConfig();
            }
            catch
            {
                PrintError("Your config seems to be corrupted. Will load defaults.");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void LoadDefaultConfig()
        {
            config = new ConfigData();
        }

        protected override void SaveConfig() => Config.WriteObject(config);
        #endregion

        private Dictionary<ulong, PlayerState> playerStates = new Dictionary<ulong, PlayerState>();
        private Dictionary<ulong, Timer> _timers = new Dictionary<ulong, Timer>();

        private void Loaded()
        {
            timer.Every(config.checkInterval, CheckPlayerProximity);
        }

        private void CheckPlayerProximity()
        {
            var players = new List<BasePlayer>();
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player != null && player.IsConnected && (!config.skipAdmin || !player.IsAdmin))
                {
                    players.Add(player);
                    if (!playerStates.ContainsKey(player.userID))
                    {
                        playerStates[player.userID] = new PlayerState();
                    }
                }
            }

            var playerGroups = DividePlayersByRegion(players);

            foreach (var group in playerGroups)
            {
                CheckPlayerDistancesInGroup(group);
            }
        }

        private List<List<BasePlayer>> DividePlayersByRegion(List<BasePlayer> players)
        {
            Dictionary<Vector3, List<BasePlayer>> regions = new Dictionary<Vector3, List<BasePlayer>>();

            foreach (var player in players)
            {
                Vector3 region = new Vector3(
                    Mathf.Floor(player.transform.position.x / config.regionSize),
                    Mathf.Floor(player.transform.position.y / config.regionSize),
                    Mathf.Floor(player.transform.position.z / config.regionSize)
                );

                if (!regions.ContainsKey(region))
                {
                    regions[region] = new List<BasePlayer>();
                }

                regions[region].Add(player);
            }

            return new List<List<BasePlayer>>(regions.Values);
        }

        private void CheckPlayerDistancesInGroup(List<BasePlayer> group)
        {
            HashSet<ulong> recordedPlayers = new HashSet<ulong>();
            bool anyHoldingWeapon = false;

            foreach (var player in group)
            {
                if (player == null || !player.IsConnected) continue;

                if (IsHoldingWeapon(player))
                {
                    anyHoldingWeapon = true;
                    break;
                }
            }

            if (anyHoldingWeapon)
            {
                foreach (var playerA in group)
                {
                    if (playerA == null || !playerA.IsConnected || recordedPlayers.Contains(playerA.userID) || playerStates[playerA.userID].IsRecording) continue;

                    foreach (var playerB in group)
                    {
                        if (playerB == playerA || playerB == null || !playerB.IsConnected || recordedPlayers.Contains(playerB.userID) || playerStates[playerB.userID].IsRecording) continue;

                        if (!ArePlayersTeammates(playerA, playerB))
                        {
                            float distance = Vector3.Distance(playerA.transform.position, playerB.transform.position);

                            if (distance <= config.recordingDistance && !IsInCooldown(playerA.userID) && !IsInCooldown(playerB.userID))
                            {
                                StartRecording(playerA);
                                StartRecording(playerB);

                                recordedPlayers.Add(playerA.userID);
                                recordedPlayers.Add(playerB.userID);
                            }
                        }
                    }
                }
            }
        }

        private bool IsInCooldown(ulong userId)
        {
            return playerStates.TryGetValue(userId, out PlayerState state) &&
                   UnityEngine.Time.realtimeSinceStartup - state.LastRecordingTime < config.recordingCooldown;  // 使用 UnityEngine.Time
        }

        private bool IsHoldingWeapon(BasePlayer player)
        {
            var activeItem = player?.GetActiveItem();
            return activeItem?.info?.category == ItemCategory.Weapon;
        }

        private void StartRecording(BasePlayer player)
        {
            if (player.Connection.IsRecording)
            {
                Puts($"Player {player.displayName} is already recording.");
                return;
            }

            try
            {
                player.StartDemoRecording();
                Puts($"Started demo recording for player {player.displayName}.");

                playerStates[player.userID].IsRecording = true;
                playerStates[player.userID].LastRecordingTime = UnityEngine.Time.realtimeSinceStartup;  // 使用 UnityEngine.Time

                config.totalRecordedLogs++;
                SaveConfig();

                if (config.autoRecordingLength > 0)
                {
                    if (_timers.ContainsKey(player.userID))
                    {
                        _timers[player.userID].Destroy();
                        _timers.Remove(player.userID);
                    }

                    _timers[player.userID] = timer.Once(config.autoRecordingLength * 60, () => StopRecording(player));
                }

                // Notify Discord
                if (config.discordNotifyRecordingStart)
                {
                    NotifyDiscord(player, "Recording started", true);
                }
            }
            catch (Exception ex)
            {
                Puts($"Failed to start recording for {player.displayName}: {ex.Message}");
            }
        }

        private void StopRecording(BasePlayer player)
        {
            if (!playerStates.TryGetValue(player.userID, out var state) || !state.IsRecording) return;

            player.StopDemoRecording();
            _timers.Remove(player.userID);
            state.IsRecording = false;

            player.ChatMessage("Recording complete. Please contact an admin for the demo file.");
            Puts($"Stopped recording for {player.displayName}.");

            config.totalUploadedLogs++;
            SaveConfig();

            // Notify Discord
            if (config.discordNotifyRecordingStop)
            {
                NotifyDiscord(player, "Recording stopped", false);
            }
        }

        private void NotifyDiscord(BasePlayer player, string msg, bool isStart)
        {
            if (string.IsNullOrEmpty(config.discordWebhookUrl)) return;

            var embed = new
            {
                embeds = new[]
                {
                    new
                    {
                        title = isStart ? "Recording Started" : "Recording Stopped",
                        description = msg,
                        color = config.discordMessageColor,
                        fields = new[]
                        {
                            new { name = "Player", value = player.displayName, inline = false },
                            new { name = "Steam ID", value = player.UserIDString, inline = false },
                        }
                    }
                }
            };

            string json = JsonConvert.SerializeObject(embed);

            // Send POST request using HttpWebRequest
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(config.discordWebhookUrl);
                request.Method = "POST";
                request.ContentType = "application/json";
                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write(json);
                }

                var response = (HttpWebResponse)request.GetResponse();
                if (response.StatusCode == HttpStatusCode.NoContent)
                {
                    Puts("Successfully sent Discord message.");
                }
                else
                {
                    Puts("Failed to send Discord message.");
                }
            }
            catch (Exception ex)
            {
                Puts($"Error sending Discord message: {ex.Message}");
            }
        }

        private bool ArePlayersTeammates(BasePlayer playerA, BasePlayer playerB)
        {
            return playerA != null && playerB != null && playerA.currentTeam == playerB.currentTeam && playerA.currentTeam != 0;
        }

        private class PlayerState
        {
            public bool IsRecording;
            public float LastRecordingTime;
            public int ReplayCount;
        }

        #region Commands
        [ChatCommand("battlelog")]
        void BattleLog(BasePlayer player, string command, string[] args)
        {
            if (args.Length == 0)
            {
                player.ChatMessage("Showing battle log for player: " + player.displayName);
                player.ChatMessage($"Total Recorded Logs: {config.totalRecordedLogs}");
                player.ChatMessage($"Total Uploaded Logs: {config.totalUploadedLogs}");
            }
            else if (args.Length == 1 && args[0].ToLower() == "stats")
            {
                player.ChatMessage("BattleReplay Stats:");
                player.ChatMessage($"Total Recorded Logs: {config.totalRecordedLogs}");
                player.ChatMessage($"Total Uploaded Logs: {config.totalUploadedLogs}");
            }
            else
            {
                player.ChatMessage("Invalid usage. Use '/battlelog' to view your battle log or '/battlelog stats' to view the plugin statistics.");
            }
        }

        [ChatCommand("replay")]
        void Replay(BasePlayer player, string command, string[] args)
        {
            if (playerStates[player.userID].ReplayCount >= config.maxReplayRecordings)
            {
                player.ChatMessage("You have reached the maximum number of replay recordings.");
                return;
            }

            if (args.Length != 1)
            {
                player.ChatMessage("Usage: /replay <playername|playerid>");
                return;
            }

            string input = args[0];
            BasePlayer targetPlayer = null;

            if (ulong.TryParse(input, out ulong playerId))
            {
                targetPlayer = BasePlayer.FindByID(playerId);
            }
            else
            {
                targetPlayer = BasePlayer.Find(input);
            }

            if (targetPlayer != null)
            {
                Puts($"Starting replay recording for player {targetPlayer.displayName} (ID: {targetPlayer.userID})");

                StartRecording(targetPlayer);

                playerStates[player.userID].ReplayCount++;

                player.ChatMessage($"Started recording for {targetPlayer.displayName}, regardless of distance.");

                _timers[targetPlayer.userID] = timer.Once(config.replayDuration * 60, () => StopRecording(targetPlayer));
            }
            else
            {
                player.ChatMessage("Player not found. Please provide a valid player name or ID.");
                Puts($"Failed to find player: {input}");
            }
        }
        #endregion

        #region Permissions
        private void Init()
        {
            permission.RegisterPermission("battlereplay.admin", this);
        }
        #endregion
    }
}

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