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

FREE BlockStatus : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using System.Collections.Generic;
using System;
using Newtonsoft.Json;
using Oxide.Core.Libraries;
using Time = UnityEngine.Time;

namespace Oxide.Plugins
{
    [Info("Block Status", "BlackWolf", "1.0.0")]
    public class BlockStatus : RustPlugin
    {
        [PluginReference]
        private Plugin CombatBlock, RaidBlock, ImageLibrary;

        #region Fields
        private const string PermissionAdmin = "blockstatus.admin";
        private const string PermissionHide = "blockstatus.hide";
        
        // UI Elements
        private Dictionary<ulong, string> activeUi = new Dictionary<ulong, string>();
        private Dictionary<ulong, Timer> uiUpdateTimers = new Dictionary<ulong, Timer>();
        
        // Configuration
        private ConfigData config;

        private class ConfigData
        {
            [JsonProperty("UI Position")]
            public UiPosition UiPos = new UiPosition { AnchorMin = "0.8 0.8", AnchorMax = "0.99 0.98" };
            
            [JsonProperty("Combat Block Settings")]
            public BlockSettings CombatBlockSettings = new BlockSettings 
            { 
                Enabled = true,
                Icon = "⚔",
                Title = "COMBAT BLOCK",
                Color = "#FF6600",
                Position = 0
            };
            
            [JsonProperty("Raid Block Settings")]
            public BlockSettings RaidBlockSettings = new BlockSettings 
            { 
                Enabled = true,
                Icon = "💣",
                Title = "RAID BLOCK",
                Color = "#FF0000",
                Position = 1
            };
            
            [JsonProperty("Background Color")]
            public string BackgroundColor = "0 0 0 0.8";
            
            [JsonProperty("Text Color")]
            public string TextColor = "1 1 1 1";
            
            [JsonProperty("Update Interval (seconds)")]
            public float UpdateInterval = 1f;
            
            [JsonProperty("Spacing Between Blocks")]
            public float Spacing = 0.05f;
            
            [JsonProperty("Show Block Time Remaining")]
            public bool ShowTimeRemaining = true;
        }

        private class BlockSettings
        {
            [JsonProperty("Enable this block type")]
            public bool Enabled = true;
            
            [JsonProperty("Icon")]
            public string Icon = "⚔";
            
            [JsonProperty("Title")]
            public string Title = "BLOCK";
            
            [JsonProperty("Color (hex)")]
            public string Color = "#FFFFFF";
            
            [JsonProperty("Position (0 = top, 1 = middle, etc.)")]
            public int Position = 0;
        }

        private class UiPosition
        {
            public string AnchorMin;
            public string AnchorMax;
        }
        
        // Block status tracking
        private class PlayerBlockStatus
        {
            public bool IsCombatBlocked;
            public float CombatTimeRemaining;
            public bool IsRaidBlocked;
            public float RaidTimeRemaining;
        }
        
        private Dictionary<ulong, PlayerBlockStatus> playerBlockStatus = new Dictionary<ulong, PlayerBlockStatus>();
        #endregion

        #region Initialization
        private void Init()
        {
            permission.RegisterPermission(PermissionAdmin, this);
            permission.RegisterPermission(PermissionHide, this);
            cmd.AddChatCommand("blockstatus", this, CmdBlockStatus);
            LoadConfig();
        }

        protected override void LoadDefaultConfig()
        {
            Config.WriteObject(new ConfigData(), true);
        }

        private void LoadConfig()
        {
            config = Config.ReadObject<ConfigData>();
            if (config == null) LoadDefaultConfig();
        }

        private void OnServerInitialized()
        {
            // Check for required plugins
            if (CombatBlock == null || RaidBlock == null)
            {
                PrintError("CombatBlock or RaidBlock plugin not found! BlockStatus requires both plugins to function.");
                return;
            }
            
            // Clean up any existing data
            foreach (var timer in uiUpdateTimers.Values)
                timer?.Destroy();
            uiUpdateTimers.Clear();
            activeUi.Clear();
            playerBlockStatus.Clear();
            
            // Start periodic updates
            timer.Every(config.UpdateInterval, UpdateAllPlayers);
        }

        private void Unload()
        {
            foreach (var timer in uiUpdateTimers.Values)
                timer?.Destroy();
            
            foreach (var player in BasePlayer.activePlayerList)
                DestroyUI(player);
        }
        #endregion

        #region Block Status Methods
        private void UpdateAllPlayers()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected) continue;
                UpdatePlayerBlockStatus(player);
            }
        }
        
        private void UpdatePlayerBlockStatus(BasePlayer player)
        {
            if (player == null || !player.IsConnected) return;
            
            // Skip if player has hide permission
            if (permission.UserHasPermission(player.UserIDString, PermissionHide))
            {
                DestroyUI(player);
                return;
            }
            
            // Get current block status
            bool isCombatBlocked = false;
            float combatTimeRemaining = 0f;
            bool isRaidBlocked = false;
            float raidTimeRemaining = 0f;
            
            // Check CombatBlock status
            if (config.CombatBlockSettings.Enabled && CombatBlock != null)
            {
                object combatResult = CombatBlock.Call("IsPlayerCombatBlocked", player.userID);
                if (combatResult is bool && (bool)combatResult)
                {
                    isCombatBlocked = true;
                    object timeResult = CombatBlock.Call("GetPlayerCombatTimeRemaining", player.userID);
                    if (timeResult is float)
                        combatTimeRemaining = (float)timeResult;
                }
            }
            
            // Check RaidBlock status
            if (config.RaidBlockSettings.Enabled && RaidBlock != null)
            {
                object raidResult = RaidBlock.Call("IsPlayerBlocked", player.userID);
                if (raidResult is bool && (bool)raidResult)
                {
                    isRaidBlocked = true;
                    object timeResult = RaidBlock.Call("GetPlayerRaidTimeRemaining", player.userID);
                    if (timeResult is float)
                        raidTimeRemaining = (float)timeResult;
                }
            }
            
            // Update player status
            var status = playerBlockStatus.ContainsKey(player.userID) 
                ? playerBlockStatus[player.userID] 
                : new PlayerBlockStatus();
                
            status.IsCombatBlocked = isCombatBlocked;
            status.CombatTimeRemaining = combatTimeRemaining;
            status.IsRaidBlocked = isRaidBlocked;
            status.RaidTimeRemaining = raidTimeRemaining;
            
            playerBlockStatus[player.userID] = status;
            
            // Update UI
            if (isCombatBlocked || isRaidBlocked)
                CreateUI(player);
            else
                DestroyUI(player);
        }
        #endregion

        #region UI Methods
        private void CreateUI(BasePlayer player)
        {
            if (player == null || !player.IsConnected) return;
            
            try
            {
                DestroyUI(player);
                
                var status = playerBlockStatus.ContainsKey(player.userID) 
                    ? playerBlockStatus[player.userID] 
                    : new PlayerBlockStatus();
                
                // Skip if no active blocks
                if (!status.IsCombatBlocked && !status.IsRaidBlocked)
                    return;
                
                var elements = new CuiElementContainer();
                
                // Create parent panel
                elements.Add(new CuiPanel
                {
                    Image = { Color = "0 0 0 0" },
                    RectTransform = { AnchorMin = config.UiPos.AnchorMin, AnchorMax = config.UiPos.AnchorMax }
                }, "Hud", "BlockStatus_UI");
                
                // Add block panels
                List<BlockInfo> activeBlocks = new List<BlockInfo>();
                
                if (status.IsCombatBlocked && config.CombatBlockSettings.Enabled)
                {
                    activeBlocks.Add(new BlockInfo
                    {
                        Type = "Combat",
                        Settings = config.CombatBlockSettings,
                        TimeRemaining = status.CombatTimeRemaining
                    });
                }
                
                if (status.IsRaidBlocked && config.RaidBlockSettings.Enabled)
                {
                    activeBlocks.Add(new BlockInfo
                    {
                        Type = "Raid",
                        Settings = config.RaidBlockSettings,
                        TimeRemaining = status.RaidTimeRemaining
                    });
                }
                
                // Sort blocks by position
                activeBlocks.Sort((a, b) => a.Settings.Position.CompareTo(b.Settings.Position));
                
                // Calculate panel heights and positions
                float panelHeight = 1.0f / activeBlocks.Count;
                float spacing = config.Spacing / activeBlocks.Count;
                
                for (int i = 0; i < activeBlocks.Count; i++)
                {
                    var block = activeBlocks[i];
                    float yMin = 1f - ((i + 1) * panelHeight) + (spacing * i);
                    float yMax = 1f - (i * panelHeight) - (spacing * i);
                    
                    string panelName = $"BlockStatus_{block.Type}";
                    string timerName = $"BlockStatus_{block.Type}_Timer";
                    
                    // Add block panel
                    elements.Add(new CuiPanel
                    {
                        Image = { Color = config.BackgroundColor },
                        RectTransform = { AnchorMin = $"0 {yMin}", AnchorMax = $"1 {yMax}" }
                    }, "BlockStatus_UI", panelName);
                    
                    // Add colored bar on the left
                    elements.Add(new CuiPanel
                    {
                        Image = { Color = HexToRustColor(block.Settings.Color) },
                        RectTransform = { AnchorMin = "0 0", AnchorMax = "0.02 1" }
                    }, panelName);
                    
                    // Block text with icon
                    elements.Add(new CuiLabel
                    {
                        Text = 
                        {
                            Text = $"{block.Settings.Icon} {block.Settings.Title}",
                            FontSize = 12,
                            Font = "robotocondensed-bold.ttf",
                            Color = HexToRustColor(block.Settings.Color),
                            Align = TextAnchor.MiddleLeft
                        },
                        RectTransform = { AnchorMin = "0.05 0.5", AnchorMax = "0.6 1" }
                    }, panelName);
                    
                    // Timer text
                    if (config.ShowTimeRemaining)
                    {
                        elements.Add(new CuiLabel
                        {
                            Text = 
                            {
                                Text = $"{block.TimeRemaining:F0}s",
                                FontSize = 12,
                                Font = "robotocondensed-bold.ttf",
                                Color = config.TextColor,
                                Align = TextAnchor.MiddleRight
                            },
                            RectTransform = { AnchorMin = "0.65 0.5", AnchorMax = "0.95 1" }
                        }, panelName, timerName);
                    }
                }
                
                // Store and send UI
                var json = CuiHelper.ToJson(elements);
                activeUi[player.userID] = json;
                CuiHelper.AddUi(player, json);
                
                // Start timer updates if needed
                if (config.ShowTimeRemaining)
                {
                    if (uiUpdateTimers.ContainsKey(player.userID))
                        uiUpdateTimers[player.userID]?.Destroy();
                    
                    uiUpdateTimers[player.userID] = timer.Every(1f, () => UpdateTimerText(player));
                }
            }
            catch (Exception ex)
            {
                PrintError($"Error creating UI for {player.displayName}: {ex.Message}\nStack: {ex.StackTrace}");
            }
        }
        
        private void UpdateTimerText(BasePlayer player)
        {
            if (player == null || !player.IsConnected) 
            {
                if (uiUpdateTimers.ContainsKey(player.userID))
                {
                    uiUpdateTimers[player.userID]?.Destroy();
                    uiUpdateTimers.Remove(player.userID);
                }
                return;
            }
            
            try
            {
                var status = playerBlockStatus.ContainsKey(player.userID) 
                    ? playerBlockStatus[player.userID] 
                    : new PlayerBlockStatus();
                
                // Update combat block timer
                if (status.IsCombatBlocked && config.CombatBlockSettings.Enabled)
                {
                    object timeResult = CombatBlock.Call("GetPlayerCombatTimeRemaining", player.userID);
                    if (timeResult is float)
                    {
                        float remaining = (float)timeResult;
                        status.CombatTimeRemaining = remaining;
                        
                        var elements = new CuiElementContainer();
                        elements.Add(new CuiLabel
                        {
                            Text = 
                            {
                                Text = $"{remaining:F0}s",
                                FontSize = 12,
                                Font = "robotocondensed-bold.ttf",
                                Color = remaining <= 10 ? "1 0.3 0.3 1" : config.TextColor,
                                Align = TextAnchor.MiddleRight
                            },
                            RectTransform = { AnchorMin = "0.65 0.5", AnchorMax = "0.95 1" }
                        }, "BlockStatus_Combat", "BlockStatus_Combat_Timer");
                        
                        CuiHelper.DestroyUi(player, "BlockStatus_Combat_Timer");
                        CuiHelper.AddUi(player, CuiHelper.ToJson(elements));
                    }
                }
                
                // Update raid block timer
                if (status.IsRaidBlocked && config.RaidBlockSettings.Enabled)
                {
                    object timeResult = RaidBlock.Call("GetPlayerRaidTimeRemaining", player.userID);
                    if (timeResult is float)
                    {
                        float remaining = (float)timeResult;
                        status.RaidTimeRemaining = remaining;
                        
                        var elements = new CuiElementContainer();
                        elements.Add(new CuiLabel
                        {
                            Text = 
                            {
                                Text = $"{remaining:F0}s",
                                FontSize = 12,
                                Font = "robotocondensed-bold.ttf",
                                Color = remaining <= 10 ? "1 0.3 0.3 1" : config.TextColor,
                                Align = TextAnchor.MiddleRight
                            },
                            RectTransform = { AnchorMin = "0.65 0.5", AnchorMax = "0.95 1" }
                        }, "BlockStatus_Raid", "BlockStatus_Raid_Timer");
                        
                        CuiHelper.DestroyUi(player, "BlockStatus_Raid_Timer");
                        CuiHelper.AddUi(player, CuiHelper.ToJson(elements));
                    }
                }
                
                playerBlockStatus[player.userID] = status;
                
                // If no blocks are active anymore, destroy the UI
                if (!status.IsCombatBlocked && !status.IsRaidBlocked)
                {
                    DestroyUI(player);
                    if (uiUpdateTimers.ContainsKey(player.userID))
                    {
                        uiUpdateTimers[player.userID]?.Destroy();
                        uiUpdateTimers.Remove(player.userID);
                    }
                }
            }
            catch (Exception ex)
            {
                PrintError($"Error updating timer for {player.displayName}: {ex.Message}");
            }
        }

        private void DestroyUI(BasePlayer player)
        {
            if (player == null) return;
            
            CuiHelper.DestroyUi(player, "BlockStatus_UI");
            
            if (activeUi.ContainsKey(player.userID))
                activeUi.Remove(player.userID);
                
            if (uiUpdateTimers.ContainsKey(player.userID))
            {
                uiUpdateTimers[player.userID]?.Destroy();
                uiUpdateTimers.Remove(player.userID);
            }
        }
        
        private string HexToRustColor(string hex)
        {
            if (string.IsNullOrEmpty(hex)) return "1 1 1 1";
            
            try
            {
                hex = hex.TrimStart('#');
                int len = hex.Length;
                
                if (len != 6 && len != 8)
                    return "1 1 1 1";
                
                float r = int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber) / 255f;
                float g = int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber) / 255f;
                float b = int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber) / 255f;
                float a = len == 8 ? int.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber) / 255f : 1f;
                
                return $"{r} {g} {b} {a}";
            }
            catch
            {
                return "1 1 1 1";
            }
        }
        
        private class BlockInfo
        {
            public string Type;
            public BlockSettings Settings;
            public float TimeRemaining;
        }
        #endregion

        #region Commands
        private void CmdBlockStatus(BasePlayer player, string command, string[] args)
        {
            if (args.Length == 0)
            {
                SendReply(player, "Usage: /blockstatus <toggle/reload>");
                return;
            }

            switch (args[0].ToLower())
            {
                case "toggle":
                    ToggleBlockStatus(player);
                    break;
                    
                case "reload":
                    if (!permission.UserHasPermission(player.UserIDString, PermissionAdmin))
                    {
                        SendReply(player, "You don't have permission to reload the configuration!");
                        return;
                    }
                    
                    LoadConfig();
                    SendReply(player, "BlockStatus configuration reloaded!");
                    UpdateAllPlayers();
                    break;
                    
                default:
                    SendReply(player, "Usage: /blockstatus <toggle/reload>");
                    break;
            }
        }
        
        private void ToggleBlockStatus(BasePlayer player)
        {
            if (permission.UserHasPermission(player.UserIDString, PermissionHide))
            {
                permission.RevokeUserPermission(player.UserIDString, PermissionHide);
                SendReply(player, "Block status display enabled!");
                UpdatePlayerBlockStatus(player);
            }
            else
            {
                permission.GrantUserPermission(player.UserIDString, PermissionHide, this);
                SendReply(player, "Block status display disabled!");
                DestroyUI(player);
            }
        }
        #endregion

        #region Hooks
        private void OnPlayerConnected(BasePlayer player)
        {
            UpdatePlayerBlockStatus(player);
        }
        
        private void OnPlayerDisconnected(BasePlayer player)
        {
            if (uiUpdateTimers.ContainsKey(player.userID))
            {
                uiUpdateTimers[player.userID]?.Destroy();
                uiUpdateTimers.Remove(player.userID);
            }
            
            if (activeUi.ContainsKey(player.userID))
                activeUi.Remove(player.userID);
                
            if (playerBlockStatus.ContainsKey(player.userID))
                playerBlockStatus.Remove(player.userID);
        }
        #endregion
    }
}

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