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

FREE CustomVitalsManager : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("CustomVitalsManager", "ifte", "1.0.0")]
    [Description("A plugin to manage custom vitals (status effects) with icons, text, timers, and more. Supports player-specific and shared vitals all using Rust Native CustomVitalsInfo")]
    public class CustomVitalsManager : RustPlugin
    {

        /*------------------------------------
         *
         *     CustomVitalsManager by Ifte
         *     Support: https://discord.gg/cCWadjcapr
         *     Fiverr: https://www.fiverr.com/s/e2pkYY
         *     
         *     Special thanks to CarbonMod
         *     https://carbonmod.gg/
         *
         ------------------------------------*/

        #region Vars

        private static CustomVitalsManager Instance;

        private readonly VitalDictionary<SharedIdentifiableVital> _sharedVitals = new VitalDictionary<SharedIdentifiableVital>();
        private readonly Dictionary<ulong, VitalDictionary<PlayerIdentifiableVital>> _playerVitals = new Dictionary<ulong, VitalDictionary<PlayerIdentifiableVital>>();

        private const uint DefaultStartVitalId = 100;
        private uint _nextVitalId = DefaultStartVitalId;

        private readonly float SendOnConnectDelay = 1f;
        private readonly bool Debug = false;

        #endregion

        #region Oxide Hooks

        private void Init()
        {
            Instance = this;
        }

        private void OnServerInitialized()
        {
            SendVitalsToEveryone();
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            if (!IsValidPlayer(player))
                return;

            timer.Once(Mathf.Max(0f, SendOnConnectDelay), () =>
            {
                if (IsValidPlayer(player))
                    SendVitals(player);
            });
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (!IsValidPlayer(player))
                return;

            ClearVitals(player, false);

        }

        private void Unload()
        {
            foreach (var dict in _playerVitals.Values)
                dict.ClearVitals(false);

            _playerVitals.Clear();
            _sharedVitals.ClearVitals(false);

            Instance = null;
        }

        #endregion

        #region Public API - Creation

        /// <summary>
        /// API: Create a ProtoBuf.CustomVitalInfo object.
        /// Other plugins may call:
        /// CustomVitalsManager.Call("API_RentVitalInfo", "ImageLibraryID", "#FFFFFF", "#000000AA", "LEFT", "#FFFFFF", "RIGHT", "#FFFFFF", 60, true)
        /// </summary>
        private CustomVitalInfo API_RentVitalInfo(
            string icon = null,
            string iconColor = null,
            string backgroundColor = null,
            string leftText = null,
            string leftTextColor = null,
            string rightText = null,
            string rightTextColor = null,
            int timeLeft = 0,
            bool active = true)
        {
            return RentVitalInfo(
                icon,
                ParseColor(iconColor, Color.white),
                ParseColor(backgroundColor, default(Color)),
                leftText,
                ParseColor(leftTextColor, Color.white),
                rightText,
                ParseColor(rightTextColor, Color.white),
                timeLeft,
                active);
        }

        /// <summary>
        /// API: Create a ProtoBuf.CustomVitalInfo object using Unity Color values directly.
        /// </summary>
        private CustomVitalInfo API_RentVitalInfoRaw(
            string icon = null,
            Color iconColor = default(Color),
            Color backgroundColor = default(Color),
            string leftText = null,
            Color leftTextColor = default(Color),
            string rightText = null,
            Color rightTextColor = default(Color),
            int timeLeft = 0,
            bool active = true)
        {
            return RentVitalInfo(icon, iconColor, backgroundColor, leftText, leftTextColor, rightText, rightTextColor, timeLeft, active);
        }

        /// <summary>
        /// API: Add a player-specific vital from a CustomVitalInfo object. Returns uint vital id, or 0 on failure.
        /// </summary>
        private uint API_AddVital(BasePlayer player, CustomVitalInfo vital, float expiry = 0f, bool sendUpdate = true)
        {
            var result = AddVital(player, vital, expiry, sendUpdate);
            return result?.Id ?? 0u;
        }

        /// <summary>
        /// API: Add a player-specific vital from simple values. Returns uint vital id, or 0 on failure.
        /// </summary>
        private uint API_AddVital(
            BasePlayer player,
            string icon = null,
            string iconColor = null,
            string backgroundColor = null,
            string leftText = null,
            string leftTextColor = null,
            string rightText = null,
            string rightTextColor = null,
            int timeLeft = 0,
            bool active = true,
            float expiry = 0f,
            bool sendUpdate = true)
        {
            var info = API_RentVitalInfo(icon, iconColor, backgroundColor, leftText, leftTextColor, rightText, rightTextColor, timeLeft, active);
            return API_AddVital(player, info, expiry, sendUpdate);
        }

        /// <summary>
        /// API: Add a player-specific vital by user id. Returns uint vital id, or 0 on failure.
        /// </summary>
        private uint API_AddPlayerVital(
            ulong playerId,
            string icon = null,
            string iconColor = null,
            string backgroundColor = null,
            string leftText = null,
            string leftTextColor = null,
            string rightText = null,
            string rightTextColor = null,
            int timeLeft = 0,
            bool active = true,
            float expiry = 0f,
            bool sendUpdate = true)
        {
            var player = BasePlayer.FindByID(playerId);
            if (!IsValidPlayer(player))
                return 0u;

            return API_AddVital(player, icon, iconColor, backgroundColor, leftText, leftTextColor, rightText, rightTextColor, timeLeft, active, expiry, sendUpdate);
        }

        /// <summary>
        /// API: Add a shared vital from a CustomVitalInfo object. Shared vitals are visible to every connected player.
        /// Returns uint vital id, or 0 on failure.
        /// </summary>
        private uint API_AddSharedVital(CustomVitalInfo vital, float expiry = 0f, bool sendUpdate = true)
        {
            var result = AddSharedVital(vital, expiry, sendUpdate);
            return result?.Id ?? 0u;
        }

        /// <summary>
        /// API: Add a shared vital from simple values. Returns uint vital id, or 0 on failure.
        /// </summary>
        private uint API_AddSharedVital(
            string icon = null,
            string iconColor = null,
            string backgroundColor = null,
            string leftText = null,
            string leftTextColor = null,
            string rightText = null,
            string rightTextColor = null,
            int timeLeft = 0,
            bool active = true,
            float expiry = 0f,
            bool sendUpdate = true)
        {
            var info = API_RentVitalInfo(icon, iconColor, backgroundColor, leftText, leftTextColor, rightText, rightTextColor, timeLeft, active);
            return API_AddSharedVital(info, expiry, sendUpdate);
        }

        #endregion

        #region Public API - Lookup / Counts

        private int API_GetSharedVitalCount() => _sharedVitals.Count;

        private int API_GetPlayerVitalCount(BasePlayer player)
        {
            return IsValidPlayer(player) ? API_GetPlayerVitalCount(player.userID) : 0;
        }

        private int API_GetPlayerVitalCount(ulong playerId)
        {
            return _playerVitals.TryGetValue(playerId, out var vitals) ? vitals.Count : 0;
        }

        private int API_GetTotalPlayerVitalCount(BasePlayer player)
        {
            return IsValidPlayer(player) ? API_GetTotalPlayerVitalCount(player.userID) : 0;
        }

        private int API_GetTotalPlayerVitalCount(ulong playerId)
        {
            return _sharedVitals.Count + API_GetPlayerVitalCount(playerId);
        }

        private bool API_HasVital(BasePlayer player, uint id)
        {
            return IsValidPlayer(player) && _playerVitals.TryGetValue(player.userID, out var vitals) && vitals.Contains(id);
        }

        private bool API_HasVital(ulong playerId, uint id)
        {
            return _playerVitals.TryGetValue(playerId, out var vitals) && vitals.Contains(id);
        }

        private bool API_HasSharedVital(uint id)
        {
            return _sharedVitals.Contains(id);
        }

        private Dictionary<string, object> API_GetVitalInfo(BasePlayer player, uint id)
        {
            return IsValidPlayer(player) && _playerVitals.TryGetValue(player.userID, out var vitals) && vitals.TryGetVital(id, out var vital)
                ? vital.ToApiDictionary()
                : null;
        }

        private Dictionary<string, object> API_GetVitalInfo(ulong playerId, uint id)
        {
            return _playerVitals.TryGetValue(playerId, out var vitals) && vitals.TryGetVital(id, out var vital)
                ? vital.ToApiDictionary()
                : null;
        }

        private Dictionary<string, object> API_GetSharedVitalInfo(uint id)
        {
            return _sharedVitals.TryGetVital(id, out var vital)
                ? vital.ToApiDictionary()
                : null;
        }

        #endregion

        #region Public API - Update

        private bool API_UpdateVitalText(BasePlayer player, uint id, string leftText = null, string rightText = null, bool sendUpdate = true)
        {
            if (!IsValidPlayer(player) || !_playerVitals.TryGetValue(player.userID, out var vitals) || !vitals.TryGetVital(id, out var vital))
                return false;

            if (leftText != null)
                vital.Info.leftText = leftText;

            if (rightText != null)
                vital.Info.rightText = rightText;

            MarkVitalUpdated(player, vital, false, sendUpdate);
            return true;
        }

        private bool API_UpdateVitalText(ulong playerId, uint id, string leftText = null, string rightText = null, bool sendUpdate = true)
        {
            return API_UpdateVitalText(BasePlayer.FindByID(playerId), id, leftText, rightText, sendUpdate);
        }

        private bool API_UpdateSharedVitalText(uint id, string leftText = null, string rightText = null, bool sendUpdate = true)
        {
            if (!_sharedVitals.TryGetVital(id, out var vital))
                return false;

            if (leftText != null)
                vital.Info.leftText = leftText;

            if (rightText != null)
                vital.Info.rightText = rightText;

            MarkSharedVitalUpdated(vital, sendUpdate);
            return true;
        }

        private bool API_SetVitalActive(BasePlayer player, uint id, bool active, bool sendUpdate = true)
        {
            if (!IsValidPlayer(player) || !_playerVitals.TryGetValue(player.userID, out var vitals) || !vitals.TryGetVital(id, out var vital))
                return false;

            vital.Info.active = active;
            MarkVitalUpdated(player, vital, false, sendUpdate);
            return true;
        }

        private bool API_SetVitalActive(ulong playerId, uint id, bool active, bool sendUpdate = true)
        {
            return API_SetVitalActive(BasePlayer.FindByID(playerId), id, active, sendUpdate);
        }

        private bool API_SetSharedVitalActive(uint id, bool active, bool sendUpdate = true)
        {
            if (!_sharedVitals.TryGetVital(id, out var vital))
                return false;

            vital.Info.active = active;
            MarkSharedVitalUpdated(vital, sendUpdate);
            return true;
        }

        private bool API_SetVitalTimeLeft(BasePlayer player, uint id, int timeLeft, bool sendUpdate = true)
        {
            if (!IsValidPlayer(player) || !_playerVitals.TryGetValue(player.userID, out var vitals) || !vitals.TryGetVital(id, out var vital))
                return false;

            vital.SetTimeLeft(timeLeft);
            MarkVitalUpdated(player, vital, false, sendUpdate);
            return true;
        }

        private bool API_SetVitalTimeLeft(ulong playerId, uint id, int timeLeft, bool sendUpdate = true)
        {
            return API_SetVitalTimeLeft(BasePlayer.FindByID(playerId), id, timeLeft, sendUpdate);
        }

        private bool API_SetSharedVitalTimeLeft(uint id, int timeLeft, bool sendUpdate = true)
        {
            if (!_sharedVitals.TryGetVital(id, out var vital))
                return false;

            vital.SetTimeLeft(timeLeft);
            MarkSharedVitalUpdated(vital, sendUpdate);
            return true;
        }

        private bool API_SetVitalExpiry(BasePlayer player, uint id, float expiry, bool restart = true)
        {
            if (!IsValidPlayer(player) || !_playerVitals.TryGetValue(player.userID, out var vitals) || !vitals.TryGetVital(id, out var vital))
                return false;

            vital.Expiry = Mathf.Max(0f, expiry);
            if (restart)
                vital.RestartExpiry();

            return true;
        }

        private bool API_SetVitalExpiry(ulong playerId, uint id, float expiry, bool restart = true)
        {
            return API_SetVitalExpiry(BasePlayer.FindByID(playerId), id, expiry, restart);
        }

        private bool API_SetSharedVitalExpiry(uint id, float expiry, bool restart = true)
        {
            if (!_sharedVitals.TryGetVital(id, out var vital))
                return false;

            vital.Expiry = Mathf.Max(0f, expiry);
            if (restart)
                vital.RestartExpiry();

            return true;
        }

        #endregion

        #region Public API - Remove / Clear / Send

        private bool API_RemoveVital(BasePlayer player, uint id, bool sendUpdate = true)
        {
            return RemoveVital(player, id, sendUpdate);
        }

        private bool API_RemoveVital(ulong playerId, uint id, bool sendUpdate = true)
        {
            return RemoveVital(BasePlayer.FindByID(playerId), id, sendUpdate);
        }

        private bool API_RemoveSharedVital(uint id, bool sendUpdate = true)
        {
            return RemoveSharedVital(id, sendUpdate);
        }

        private void API_ClearVitals(BasePlayer player, bool sendUpdate = true)
        {
            ClearVitals(player, sendUpdate);
        }

        private void API_ClearPlayerVitals(BasePlayer player, bool sendUpdate = true)
        {
            ClearVitals(player, sendUpdate);
        }

        private void API_ClearPlayerVitals(ulong playerId, bool sendUpdate = true)
        {
            ClearVitals(BasePlayer.FindByID(playerId), sendUpdate);
        }

        private void API_ClearSharedVitals(bool sendUpdate = true)
        {
            ClearSharedVitals(sendUpdate);
        }

        private void API_SendVitals(BasePlayer player)
        {
            SendVitals(player);
        }

        private void API_SendVitals(ulong playerId)
        {
            SendVitals(BasePlayer.FindByID(playerId));
        }

        private void API_SendVitalsToEveryone()
        {
            SendVitalsToEveryone();
        }

        #endregion

        #region Internal Manager Methods

        public CustomVitalInfo RentVitalInfo(
            string icon = null,
            Color iconColor = default(Color),
            Color backgroundColor = default(Color),
            string leftText = null,
            Color leftTextColor = default(Color),
            string rightText = null,
            Color rightTextColor = default(Color),
            int timeLeft = 0,
            bool active = true)
        {
            var vitalInfo = Pool.Get<CustomVitalInfo>();

            vitalInfo.icon = icon;
            vitalInfo.iconColor = iconColor;
            vitalInfo.backgroundColor = backgroundColor;
            vitalInfo.leftText = leftText;
            vitalInfo.leftTextColor = leftTextColor;
            vitalInfo.rightText = rightText;
            vitalInfo.rightTextColor = rightTextColor;
            vitalInfo.timeLeft = timeLeft;
            vitalInfo.active = active;

            return vitalInfo;
        }

        public PlayerIdentifiableVital AddVital(BasePlayer player, CustomVitalInfo vital, float expiry = 0f, bool sendUpdate = true)
        {
            if (!IsValidPlayer(player) || vital == null)
                return null;

            var hookResult = Interface.CallHook("CanAddCustomVital", player, vital, false);
            if (hookResult is bool allowed && !allowed)
                return null;

            if (!_playerVitals.TryGetValue(player.userID, out var vitals))
            {
                vitals = new VitalDictionary<PlayerIdentifiableVital>();
                _playerVitals[player.userID] = vitals;
            }

            var identifiableVital = vitals.AddVital(NextVitalId(), vital, expiry);
            identifiableVital.PlayerId = player.userID;

            RestartExpiry(identifiableVital);

            Interface.CallHook("OnCustomVitalAdded", player, identifiableVital.Id, false, identifiableVital.Info);

            if (sendUpdate)
                SendVitals(player);

            DebugLog($"Added player vital {identifiableVital.Id} to {player.displayName}/{player.UserIDString}");
            return identifiableVital;
        }

        public SharedIdentifiableVital AddSharedVital(CustomVitalInfo vital, float expiry = 0f, bool sendUpdate = true)
        {
            if (vital == null)
                return null;

            var hookResult = Interface.CallHook("CanAddCustomVital", null, vital, true);
            if (hookResult is bool allowed && !allowed)
                return null;

            var identifiableVital = _sharedVitals.AddVital(NextVitalId(), vital, expiry);

            RestartExpiry(identifiableVital);

            Interface.CallHook("OnCustomVitalAdded", null, identifiableVital.Id, true, identifiableVital.Info);

            if (sendUpdate)
                SendVitalsToEveryone();

            DebugLog($"Added shared vital {identifiableVital.Id}");
            return identifiableVital;
        }

        public bool RemoveVital(BasePlayer player, uint id, bool sendUpdate = true)
        {
            if (!IsValidPlayer(player) || !_playerVitals.TryGetValue(player.userID, out var vitals))
                return false;

            if (!vitals.TryGetVital(id, out var vital))
                return false;

            CancelExpiry(vital);

            if (!vitals.RemoveVital(id, true))
                return false;

            Interface.CallHook("OnCustomVitalRemoved", player, id, false);

            if (sendUpdate)
                SendVitals(player);

            DebugLog($"Removed player vital {id} from {player.displayName}/{player.UserIDString}");
            return true;
        }

        public bool RemoveSharedVital(uint id, bool sendUpdate = true)
        {
            if (!_sharedVitals.TryGetVital(id, out var vital))
                return false;

            CancelExpiry(vital);

            if (!_sharedVitals.RemoveVital(id, true))
                return false;

            Interface.CallHook("OnCustomVitalRemoved", null, id, true);

            if (sendUpdate)
                SendVitalsToEveryone();

            DebugLog($"Removed shared vital {id}");
            return true;
        }

        public void ClearVitals(BasePlayer player, bool sendUpdate = true)
        {
            if (!IsValidPlayer(player) || !_playerVitals.TryGetValue(player.userID, out var vitals))
                return;

            foreach (var vital in vitals.GetSnapshot())
                CancelExpiry(vital);

            vitals.ClearVitals(true);

            Interface.CallHook("OnCustomVitalsCleared", player, false);

            if (sendUpdate)
                SendVitals(player);

            DebugLog($"Cleared player vitals for {player.displayName}/{player.UserIDString}");
        }

        public void ClearSharedVitals(bool sendUpdate = true)
        {
            foreach (var vital in _sharedVitals.GetSnapshot())
                CancelExpiry(vital);

            _sharedVitals.ClearVitals(true);

            Interface.CallHook("OnCustomVitalsCleared", null, true);

            if (sendUpdate)
                SendVitalsToEveryone();

            DebugLog("Cleared shared vitals");
        }

        public void SendVitals(BasePlayer player)
        {
            if (!IsValidPlayer(player) || CommunityEntity.ServerInstance == null)
                return;

            var proto = Pool.Get<CustomVitals>();
            proto.vitals = Pool.Get<List<CustomVitalInfo>>();

            try
            {
                if (_playerVitals.TryGetValue(player.userID, out var playerDict))
                    playerDict.AppendVitals(proto);

                _sharedVitals.AppendVitals(proto);

                CommunityEntity.ServerInstance.SendCustomVitals(player, proto);
                Interface.CallHook("OnCustomVitalsSent", player, proto.vitals.Count);
            }
            finally
            {
                Pool.Free(ref proto.vitals);
                Pool.Free(ref proto);
            }
        }

        public void SendVitalsToEveryone()
        {
            var players = BasePlayer.activePlayerList;
            for (var i = 0; i < players.Count; i++)
                SendVitals(players[i]);
        }

        #endregion

        #region Helpers

        private uint NextVitalId()
        {
            if (_nextVitalId == uint.MaxValue)
                _nextVitalId = DefaultStartVitalId;

            return ++_nextVitalId;
        }

        private void MarkVitalUpdated(BasePlayer player, PlayerIdentifiableVital vital, bool shared, bool sendUpdate)
        {
            Interface.CallHook("OnCustomVitalUpdated", player, vital.Id, shared, vital.Info);

            if (sendUpdate)
                SendVitals(player);
        }

        private void MarkSharedVitalUpdated(SharedIdentifiableVital vital, bool sendUpdate)
        {
            Interface.CallHook("OnCustomVitalUpdated", null, vital.Id, true, vital.Info);

            if (sendUpdate)
                SendVitalsToEveryone();
        }

        private void RestartExpiry(IdentifiableVital vital)
        {
            vital.RestartExpiry();
        }

        private void CancelExpiry(IdentifiableVital vital)
        {
            vital.CancelExpiry();
        }

        private static bool IsValidPlayer(BasePlayer player)
        {
            return player != null && !player.IsDestroyed && player.userID != 0;
        }

        private static Color ParseColor(string value, Color fallback)
        {
            if (string.IsNullOrWhiteSpace(value))
                return fallback;

            value = value.Trim();

            if (value[0] == '#')
            {
                if (ColorUtility.TryParseHtmlString(value, out var parsed))
                    return parsed;

                return fallback;
            }

            var parts = value.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length < 3)
                return fallback;

            if (!float.TryParse(parts[0], out var r) ||
                !float.TryParse(parts[1], out var g) ||
                !float.TryParse(parts[2], out var b))
                return fallback;

            var a = 1f;
            if (parts.Length >= 4)
                float.TryParse(parts[3], out a);

            return new Color(r, g, b, a);
        }

        private static string ColorToString(Color color)
        {
            return $"{color.r:0.###} {color.g:0.###} {color.b:0.###} {color.a:0.###}";
        }

        private void DebugLog(string message)
        {
            if (Debug)
                Puts(message);
        }

        #endregion

        #region Data Classes

        public abstract class IdentifiableVital
        {
            public uint Id;
            public CustomVitalInfo Info;
            public int TotalTimeLeft;
            public float Expiry;

            private float _timeLeftStartedAt;
            private Timer _expiryTimer;

            public int CurrentTimeLeft
            {
                get
                {
                    if (TotalTimeLeft <= 0)
                        return 0;

                    var elapsed = Time.realtimeSinceStartup - _timeLeftStartedAt;
                    return Mathf.Max(TotalTimeLeft - Mathf.FloorToInt(elapsed), 0);
                }
            }

            public virtual void SetTimeLeft(int timeLeft)
            {
                if (Info == null)
                    return;

                Info.timeLeft = Mathf.Max(0, timeLeft);
                TotalTimeLeft = Info.timeLeft;
                _timeLeftStartedAt = Time.realtimeSinceStartup;
            }

            public abstract void SendUpdate();

            public abstract void RemoveSelf();

            public void RestartExpiry()
            {
                CancelExpiry();

                if (Expiry <= 0f)
                    return;

                _expiryTimer = Instance.timer.Once(Expiry, RemoveSelf);
            }

            public void CancelExpiry()
            {
                _expiryTimer?.Destroy();
                _expiryTimer = null;
            }

            public void FreeInfo()
            {
                if (Info == null)
                    return;

                var info = Info;
                Info = null;
                Pool.Free(ref info);
            }

            public Dictionary<string, object> ToApiDictionary()
            {
                return new Dictionary<string, object>
                {
                    ["Id"] = Id,
                    ["Icon"] = Info?.icon,
                    ["IconColor"] = Info == null ? null : ColorToString(Info.iconColor),
                    ["BackgroundColor"] = Info == null ? null : ColorToString(Info.backgroundColor),
                    ["LeftText"] = Info?.leftText,
                    ["LeftTextColor"] = Info == null ? null : ColorToString(Info.leftTextColor),
                    ["RightText"] = Info?.rightText,
                    ["RightTextColor"] = Info == null ? null : ColorToString(Info.rightTextColor),
                    ["TimeLeft"] = CurrentTimeLeft,
                    ["TotalTimeLeft"] = TotalTimeLeft,
                    ["Active"] = Info != null && Info.active,
                    ["Expiry"] = Expiry
                };
            }
        }

        public class SharedIdentifiableVital : IdentifiableVital
        {
            public override void RemoveSelf()
            {
                if (Instance == null)
                    return;

                Instance.RemoveSharedVital(Id, true);
            }

            public override void SendUpdate()
            {
                Instance?.SendVitalsToEveryone();
            }
        }

        public class PlayerIdentifiableVital : IdentifiableVital
        {
            public ulong PlayerId;

            public BasePlayer GetPlayer()
            {
                return BasePlayer.FindByID(PlayerId);
            }

            public override void RemoveSelf()
            {
                if (Instance == null)
                    return;

                var player = GetPlayer();
                if (IsValidPlayer(player))
                    Instance.RemoveVital(player, Id, true);
            }

            public override void SendUpdate()
            {
                var player = GetPlayer();
                if (IsValidPlayer(player))
                    Instance.SendVitals(player);
            }

            public new Dictionary<string, object> ToApiDictionary()
            {
                var data = base.ToApiDictionary();
                data["PlayerId"] = PlayerId;
                return data;
            }
        }

        public class VitalDictionary<T> where T : IdentifiableVital, new()
        {
            private readonly Dictionary<uint, T> _buffer = new Dictionary<uint, T>();

            public int Count => _buffer.Count;

            public bool HasAny()
            {
                return _buffer.Count > 0;
            }

            public bool Contains(uint id)
            {
                return _buffer.ContainsKey(id);
            }

            public List<T> GetSnapshot()
            {
                return new List<T>(_buffer.Values);
            }

            public void AppendVitals(CustomVitals vitals)
            {
                if (vitals == null || vitals.vitals == null)
                    return;

                foreach (var identifiableVital in _buffer.Values)
                {
                    if (identifiableVital.Info == null)
                        continue;

                    identifiableVital.Info.timeLeft = identifiableVital.CurrentTimeLeft;
                    vitals.vitals.Add(identifiableVital.Info);
                }
            }

            public T AddVital(uint id, CustomVitalInfo vital, float expiry = 0f)
            {
                var identifiableVital = new T
                {
                    Id = id,
                    Info = vital,
                    Expiry = Mathf.Max(0f, expiry)
                };

                identifiableVital.SetTimeLeft(vital.timeLeft);
                _buffer[identifiableVital.Id] = identifiableVital;
                return identifiableVital;
            }

            public bool TryGetVital(uint id, out T vital)
            {
                return _buffer.TryGetValue(id, out vital);
            }

            public bool RemoveVital(uint id, bool freeInfo)
            {
                if (!_buffer.TryGetValue(id, out var vital))
                    return false;

                vital.CancelExpiry();

                if (freeInfo)
                    vital.FreeInfo();

                return _buffer.Remove(id);
            }

            public void ClearVitals(bool freeInfo)
            {
                foreach (var vital in _buffer.Values)
                {
                    vital.CancelExpiry();

                    if (freeInfo)
                        vital.FreeInfo();
                }

                _buffer.Clear();
            }
        }

        #endregion

    }
}

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