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

FREE Leaders : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Leaders", "fufeldev", "1.0.0")]
    public class Leaders : RustPlugin {
        [PluginReference]
        private Plugin SClan, FBuildZoneStages, Stadia;
        private const string UiRoot = "Leaders_UI";
        private const int MaxRows = 7;
        private const int KillPoints = 1;
        private const int CupboardRaidPoints = 40;
        private const int BradleyCratePoints = 4;
        private const int HeliCratePoints = 5;
        private const int HeliCrateMaxPointsPerPlayer = 20;
        private const int RaidBanSeconds = 10800;
        private const string RaidBanReason = "Clan raided";
        private const string RaidBanData = "Leaders/RaidBans";
        private const string RaidAttentionColor = "#E87878";
        private const string RaidVictimColor = "#5dade2";
        private readonly Dictionary<string, string> _imageStorageIds = new Dictionary<string, string>();
        private readonly List<ClanRow> _demoRows = new List<ClanRow>();
        private readonly HashSet<ulong> _bradleyCrates = new HashSet<ulong>();
        private readonly HashSet<ulong> _scoredBradleyCrates = new HashSet<ulong>();
        private readonly HashSet<ulong> _scoredHeliCrates = new HashSet<ulong>();
        private readonly Dictionary<ulong, int> _heliCratePlayerPoints = new Dictionary<ulong, int>();
        private readonly Dictionary<ulong, long> _raidBans = new Dictionary<ulong, long>();
        private readonly Dictionary<NetworkableId, DamageEntry> _lastCupboardDamagers = new Dictionary<NetworkableId, DamageEntry>();
        private readonly Dictionary<NetworkableId, string> _cupboardClanTags = new Dictionary<NetworkableId, string>();
        private readonly Dictionary<NetworkableId, CupboardEntry> _cupboardEntries = new Dictionary<NetworkableId, CupboardEntry>();
        private readonly Dictionary<ulong, DamageEntry> _lastPlayerDamagers = new Dictionary<ulong, DamageEntry>();
        private readonly HashSet<NetworkableId> _scoredCupboards = new HashSet<NetworkableId>();
        private static readonly Dictionary<string, string> ImageFiles = new Dictionary<string, string> {
            {
                "Hudaima_Leaders_Path_2", "Hudaima_Leaders_Path_2.png"
            }
            , {
                "Hudaima_Leaders_Header_Backplate_1", "Hudaima_Leaders_Header_Backplate_1.png"
            }
            , {
                "Hudaima_Leaders_Rank_1_Badge_1", "Hudaima_Leaders_Rank_1_Badge_1.png"
            }
        }
        ;
        private class ClanRow {
            public string Tag;
            public int Points;
        }
        private class ClanSaveData {
            public string ClanTag;
            public Dictionary<ulong, ClanMemberSaveData> Members = new Dictionary<ulong, ClanMemberSaveData>();
        }
        private class ClanMemberSaveData {
            public int Point;
        }
        private class DamageEntry {
            public ulong UserId;
            public float Time;
            public string ClanTag;
            public bool HasGear;
        }
        private class CupboardEntry {
            public ulong OwnerId;
            public string ClanTag;
            public string GroupKey;
            public HashSet<ulong> UserIds = new HashSet<ulong>();
            public DamageEntry LastDamage;
        }
        private void OnServerInitialized() {
            LoadImageAssets();
            LoadRaidBans();
            ScheduleRaidBans();
            ScanCupboardClans();
            timer.Once(1f, ShowAll);
            timer.Every(10f, ShowAll);
        }
        private void OnEntitySpawned(BuildingPrivlidge priv) {
            NextTick(() => RememberCupboardState(priv));
        }
        private void OnPlayerInit(BasePlayer player) {
            QueueShow(player);
        }
        private void OnPlayerConnected(BasePlayer player) {
            QueueShow(player);
        }
        private void OnPlayerRespawned(BasePlayer player) {
            QueueShow(player);
        }
        private void OnPluginLoaded(Plugin plugin) {
            if (plugin != null && (plugin.Name == "SClan" || plugin.Name == "FBuildZoneStages")) {
                ScanCupboardClans();
            }
            if (plugin != null && plugin.Name == "SClan") {
                timer.Once(1f, ShowAll);
            }
        }
        private void OnClanCreate(string clanTag) {
            timer.Once(0.5f, ShowAll);
        }
        private void OnClanDestroy(string clanTag) {
            timer.Once(0.5f, ShowAll);
        }
        private void OnClanMemberJoined(string userID, string clanTag) {
            timer.Once(0.5f, ShowAll);
        }
        private void OnClanMemberGone(string userID, string clanTag) {
            timer.Once(0.5f, ShowAll);
        }
        private void OnPlayerDeath(BasePlayer player, HitInfo info) {
            if (player == null || player.IsNpc || !player.userID.IsSteamId()) return;
            ulong attackerId = GetAttackerId(info);
            bool hasGear = HasScorableGear(player);
            if (_lastPlayerDamagers.TryGetValue(player.userID, out DamageEntry entry) && Time.realtimeSinceStartup - entry.Time <= 300f) {
                if (!attackerId.IsSteamId()) attackerId = entry.UserId;
                if (entry.HasGear) hasGear = true;
            }
            if (!attackerId.IsSteamId() || attackerId == player.userID || IsSameClan(player.userID, attackerId) || !hasGear) return;
            AddPoints(attackerId, KillPoints);
        }
        private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
            if (!IsCupboardEntity(entity)) return;
            BuildingPrivlidge priv = GetCupboardPrivilege(entity);
            if (priv == null) return;
            ScoreCupboard(priv, info);
        }
        private void ScoreCupboard(BuildingPrivlidge priv, HitInfo info) {
            if (priv?.net == null) {
                return;
            }
            if (_scoredCupboards.Contains(priv.net.ID)) {
                return;
            }
            string phase = GetCurrentPhase();
            if (!IsRaidPhaseName(phase)) {
                return;
            }
            CupboardEntry cupboard = RememberCupboardState(priv);
            string victimClan = GetCupboardClanTag(priv, cupboard);
            ulong attackerId = GetCupboardAttackerId(priv, info, cupboard);
            BasePlayer attackerPlayer = GetAttackerPlayer(attackerId, info, priv);
            string attackerClan = GetClanTag(attackerId);
            ulong victimOwnerId = GetRaidVictimOwnerId(priv, cupboard, victimClan);
            bool own = attackerId.IsSteamId() && IsOwnCupboard(priv, attackerId, cupboard);
            if (string.IsNullOrEmpty(victimClan)) {
                return;
            }
            if (own) {
                return;
            }
            if (!string.IsNullOrEmpty(attackerClan) && string.Equals(victimClan, attackerClan, StringComparison.OrdinalIgnoreCase)) {
                return;
            }
            _scoredCupboards.Add(priv.net.ID);
            EliminateCupboardClan(priv, cupboard, victimClan, victimOwnerId, attackerId, attackerClan, attackerPlayer);
        }
        private ulong GetCupboardAttackerId(BuildingPrivlidge priv, HitInfo info, CupboardEntry cupboard) {
            ulong attackerId = GetAttackerId(info);
            if (!attackerId.IsSteamId()) attackerId = GetEntityPlayerId(priv.lastAttacker);
            if (_lastCupboardDamagers.TryGetValue(priv.net.ID, out DamageEntry entry) && Time.realtimeSinceStartup - entry.Time <= 900f) {
                if (!attackerId.IsSteamId()) attackerId = entry.UserId;
            }
            if (cupboard?.LastDamage != null && Time.realtimeSinceStartup - cupboard.LastDamage.Time <= 900f) {
                if (!attackerId.IsSteamId()) attackerId = cupboard.LastDamage.UserId;
            }
            return attackerId;
        }
        private BasePlayer GetAttackerPlayer(ulong attackerId, HitInfo info, BuildingPrivlidge priv) {
            BasePlayer player = info?.InitiatorPlayer;
            if (player != null && !player.IsNpc && player.userID.IsSteamId()) return player;
            player = priv?.lastAttacker as BasePlayer;
            if (player != null && !player.IsNpc && player.userID.IsSteamId()) return player;
            return attackerId.IsSteamId() ? BasePlayer.FindAwakeOrSleepingByID(attackerId) : null;
        }
        private ulong GetRaidVictimOwnerId(BuildingPrivlidge priv, CupboardEntry cupboard, string victimClan) {
            ulong ownerId = cupboard == null ? priv.OwnerID : cupboard.OwnerId;
            if (ownerId.IsSteamId() && string.Equals(GetClanTag(ownerId), victimClan, StringComparison.OrdinalIgnoreCase)) return ownerId;
            object result = SClan?.Call("GetOwnerId", victimClan);
            if (result is ulong userId && userId.IsSteamId()) return userId;
            if (result is string text && ulong.TryParse(text, out ulong parsed) && parsed.IsSteamId()) return parsed;
            return ownerId;
        }
        private void EliminateCupboardClan(BuildingPrivlidge priv, CupboardEntry cupboard, string victimClan, ulong victimOwnerId, ulong attackerId, string attackerClan, BasePlayer attackerPlayer) {
            List<string> members = GetClanMembers(victimClan);
            Interface.CallHook("OnTournamentClanEliminated", victimClan, members);
            AnnounceClanEliminated(priv, victimClan, attackerId, attackerClan, attackerPlayer);
            if (attackerId.IsSteamId() && !string.IsNullOrEmpty(attackerClan)) {
                AddPoints(attackerId, CupboardRaidPoints);
                SClan?.CallHook("GetPointRaid", victimOwnerId, attackerId);
            }
            BanCupboardVictims(priv, victimClan, cupboard);
            timer.Once(0.2f, ShowAll);
        }
        private void AnnounceClanEliminated(BuildingPrivlidge priv, string victimClan, ulong attackerId, string attackerClan, BasePlayer attackerPlayer) {
            Server.Broadcast(BuildRaidStartedMessage(MapHelper.PositionToString(priv.transform.position)));
        }
        private string BuildRaidStartedMessage(string grid) {
            return $"<color={RaidAttentionColor}>ВНИМАНИЕ!</color>\n<size=12>Рейд начался в квадрате <color={RaidVictimColor}>{grid}</color></size>";
        }
        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            ulong userId = GetAttackerId(info);
            if (!userId.IsSteamId()) return null;
            BasePlayer player = entity as BasePlayer;
            if (player != null && !player.IsNpc && player.userID.IsSteamId() && player.userID != userId) {
                _lastPlayerDamagers[player.userID] = new DamageEntry {
                    UserId = userId, Time = Time.realtimeSinceStartup, HasGear = HasScorableGear(player)
                }
                ;
                return null;
            }
            BuildingPrivlidge priv = GetCupboardPrivilege(entity);
            if (priv != null) {
                bool own = IsOwnCupboard(priv, userId);
                if (own) return true;
                RememberCupboardDamage(priv, userId);
            }
            return null;
        }
        private void RememberCupboardDamage(BuildingPrivlidge priv, ulong userId) {
            if (priv?.net == null) return;
            CupboardEntry cupboard = RememberCupboardState(priv);
            DamageEntry damage = new DamageEntry {
                UserId = userId, Time = Time.realtimeSinceStartup, ClanTag = GetCupboardClanTag(priv, cupboard)
            }
            ;
            _lastCupboardDamagers[priv.net.ID] = damage;
            if (cupboard != null) cupboard.LastDamage = damage;
        }
        private void OnCrateSpawned(BradleyAPC bradley, BaseEntity crate) {
            if (crate?.net == null) return;
            _bradleyCrates.Add(crate.net.ID.Value);
        }
        private void OnLootEntity(BasePlayer player, BaseEntity entity) {
            if (player == null || entity?.net == null || !player.userID.IsSteamId()) return;
            ulong id = entity.net.ID.Value;
            if (_bradleyCrates.Contains(id) || entity.ShortPrefabName == "bradley_crate") {
                if (!_scoredBradleyCrates.Add(id)) return;
                _bradleyCrates.Add(id);
                AddPoints(player.userID, BradleyCratePoints);
                return;
            }
            if (entity.ShortPrefabName == "heli_crate") {
                if (!_scoredHeliCrates.Add(id)) return;
                int current = _heliCratePlayerPoints.TryGetValue(player.userID, out var v) ? v : 0;
                if (current >= HeliCrateMaxPointsPerPlayer) return;
                int awarded = Math.Min(HeliCratePoints, HeliCrateMaxPointsPerPlayer - current);
                _heliCratePlayerPoints[player.userID] = current + awarded;
                AddPoints(player.userID, awarded);
            }
        }
        private void OnEntityKill(BaseNetworkable entity) {
            if (entity?.net == null) return;
            ulong id = entity.net.ID.Value;
            BaseEntity baseEntity = entity as BaseEntity;
            BuildingPrivlidge priv = GetCupboardPrivilege(baseEntity);
            if (priv != null) {
                ScoreCupboard(priv, null);
            }
            _bradleyCrates.Remove(id);
            _scoredBradleyCrates.Remove(id);
            _scoredHeliCrates.Remove(id);
            _lastCupboardDamagers.Remove(entity.net.ID);
            _cupboardClanTags.Remove(entity.net.ID);
            _cupboardEntries.Remove(entity.net.ID);
        }
        private void OnEntityKill(BuildingPrivlidge priv) {
            ScoreCupboard(priv, null);
            if (priv?.net != null) {
                _cupboardClanTags.Remove(priv.net.ID);
                _cupboardEntries.Remove(priv.net.ID);
            }
        }
        private void QueueShow(BasePlayer player) {
            if (player == null || player.IsNpc) {
                return;
            }
            timer.Once(2f, () => {
                if (player != null && player.IsConnected && !player.IsNpc) {
                    CreateUI(player);
                }
            }
            );
        }
        private void LoadImageAssets() {
            var imageDir = Path.Combine(Interface.Oxide.DataDirectory, "Leaders", "Images");
            Directory.CreateDirectory(imageDir);
            _imageStorageIds.Clear();
            foreach (var kv in ImageFiles) {
                var path = Path.Combine(imageDir, kv.Value);
                if (!File.Exists(path)) {
                    PrintWarning($"[UIAssets] Missing PNG file: {path}");
                    continue;
                }
                try {
                    var bytes = File.ReadAllBytes(path);
                    _imageStorageIds[kv.Key] = FileStorage.server.Store(bytes, FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
                }
                catch (Exception ex) {
                    PrintWarning($"[UIAssets] Failed to load {kv.Key}: {ex.Message}");
                }
            }
        }
        private string Img(string key) {
            return _imageStorageIds.TryGetValue(key, out var stored) ? stored : string.Empty;
        }
        [ChatCommand("leaders.show")]
        private void ShowUICommand(BasePlayer player, string command, string[] args) {
            CreateUI(player);
        }
        [ConsoleCommand("leaders.show")]
        private void ShowConsoleCommand(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) {
                ShowAll();
                return;
            }
            CreateUI(player);
        }
        [ConsoleCommand("leaders.refresh")]
        private void RefreshConsoleCommand(ConsoleSystem.Arg arg) {
            ShowAll();
        }
        [ConsoleCommand("leaders.demo")]
        private void DemoConsoleCommand(ConsoleSystem.Arg arg) {
            var args = arg.Args;
            if (args != null && args.Length > 0 && (args[0] == "clear" || args[0] == "delete" || args[0] == "remove")) {
                _demoRows.Clear();
                ShowAll();
                return;
            }
            _demoRows.Clear();
            for (var i = 1; i <= 30; i++) {
                _demoRows.Add(new ClanRow {
                    Tag = $"DEMO{i:00}", Points = 3000 - i * 73
                }
                );
            }
            ShowAll();
        }
        private void ShowAll() {
            foreach (var player in BasePlayer.activePlayerList) {
                if (player == null || !player.IsConnected || player.IsNpc) {
                    continue;
                }
                CreateUI(player);
            }
        }
        private List<ClanRow> GetClanRows() {
            var rows = new List<ClanRow>();
            if (_demoRows.Count > 0) {
                rows.AddRange(_demoRows);
                rows.Sort((a, b) => {
                    var points = b.Points.CompareTo(a.Points);
                    return points != 0 ? points : string.Compare(a.Tag, b.Tag, StringComparison.OrdinalIgnoreCase);
                }
                );
                return rows;
            }
            var tops = SClan?.Call("GetTops");
            if (tops is Dictionary<string, int> typed) {
                foreach (var kv in typed) {
                    if (!string.IsNullOrWhiteSpace(kv.Key)) {
                        rows.Add(new ClanRow {
                            Tag = kv.Key, Points = kv.Value
                        }
                        );
                    }
                }
            }
            else if (tops is Dictionary<string, object> objects) {
                foreach (var kv in objects) {
                    if (!string.IsNullOrWhiteSpace(kv.Key)) {
                        rows.Add(new ClanRow {
                            Tag = kv.Key, Points = Convert.ToInt32(kv.Value)
                        }
                        );
                    }
                }
            }
            if (rows.Count == 0) {
                rows = GetClanRowsFromData();
            }
            rows.Sort((a, b) => {
                var points = b.Points.CompareTo(a.Points);
                return points != 0 ? points : string.Compare(a.Tag, b.Tag, StringComparison.OrdinalIgnoreCase);
            }
            );
            return rows;
        }
        private List<ClanRow> GetClanRowsFromData() {
            var rows = new List<ClanRow>();
            try {
                var clans = Interface.Oxide.DataFileSystem.ReadObject<List<ClanSaveData>>("SClan/ClansList");
                if (clans == null) {
                    return rows;
                }
                foreach (var clan in clans) {
                    if (clan == null || string.IsNullOrWhiteSpace(clan.ClanTag)) {
                        continue;
                    }
                    var points = 0;
                    if (clan.Members != null) {
                        foreach (var member in clan.Members) {
                            if (member.Value != null) {
                                points += member.Value.Point;
                            }
                        }
                    }
                    rows.Add(new ClanRow {
                        Tag = clan.ClanTag, Points = points
                    }
                    );
                }
            }
            catch {
            }
            return rows;
        }
        private void AddPoints(ulong playerId, int points) {
            if (!playerId.IsSteamId() || points == 0) {
                return;
            }
            if (SClan == null) {
                return;
            }
            SClan.Call("AddPointsToPlayer", playerId, points);
            timer.Once(0.2f, ShowAll);
        }
        private string GetClanTag(ulong playerId) {
            string tag = SClan?.Call<string>("GetClanTag", playerId);
            return string.IsNullOrEmpty(tag) ? string.Empty : tag;
        }
        private bool IsSameClan(ulong playerId, ulong targetId) {
            string first = GetClanTag(playerId);
            if (string.IsNullOrEmpty(first)) return false;
            string second = GetClanTag(targetId);
            return !string.IsNullOrEmpty(second) && string.Equals(first, second, StringComparison.OrdinalIgnoreCase);
        }
        private bool IsSameGroup(ulong playerId, ulong targetId) {
            if (!playerId.IsSteamId() || !targetId.IsSteamId()) return false;
            if (playerId == targetId) return true;
            if (SClan?.Call<bool>("IsTeammate", playerId, targetId) == true) return true;
            if (IsSameClan(playerId, targetId)) return true;
            RelationshipManager.PlayerTeam team = RelationshipManager.ServerInstance?.FindPlayersTeam(playerId);
            return team != null && team.members != null && team.members.Contains(targetId);
        }
        private bool IsOwnCupboard(BuildingPrivlidge priv, ulong playerId) {
            return IsOwnCupboard(priv, playerId, null);
        }
        private bool IsOwnCupboard(BuildingPrivlidge priv, ulong playerId, CupboardEntry cupboard) {
            if (priv == null || !playerId.IsSteamId()) return false;
            if (cupboard != null) {
                if (cupboard.OwnerId == playerId) return true;
                if (cupboard.OwnerId.IsSteamId() && IsSameGroup(cupboard.OwnerId, playerId)) return true;
                if (IsOwnCupboardGroup(cupboard.GroupKey, playerId)) return true;
                foreach (ulong userId in cupboard.UserIds) {
                    if (userId != playerId && IsSameGroup(userId, playerId)) return true;
                }
            }
            if (priv.OwnerID == playerId) return true;
            if (priv.OwnerID.IsSteamId() && IsSameGroup(priv.OwnerID, playerId)) return true;
            if (IsOwnCupboardGroup(priv, playerId)) return true;
            if (priv.authorizedPlayers == null) return false;
            foreach (ulong userId in priv.authorizedPlayers) {
                if (userId != playerId && IsSameGroup(userId, playerId)) return true;
            }
            return false;
        }
        private bool IsOwnCupboardGroup(BuildingPrivlidge priv, ulong playerId) {
            Dictionary<string, object> info = FBuildZoneStages?.Call("GetCupboardInfo", priv) as Dictionary<string, object>;
            if (info == null || !info.TryGetValue("groupKey", out object value)) return false;
            string groupKey = value as string;
            return IsOwnCupboardGroup(groupKey, playerId);
        }
        private bool IsOwnCupboardGroup(string groupKey, ulong playerId) {
            if (string.IsNullOrEmpty(groupKey)) return false;
            if (groupKey.StartsWith("clan:", StringComparison.OrdinalIgnoreCase)) {
                string clan = GetClanTag(playerId);
                return !string.IsNullOrEmpty(clan) && string.Equals(clan, groupKey.Substring(5), StringComparison.OrdinalIgnoreCase);
            }
            if (groupKey.StartsWith("team:", StringComparison.OrdinalIgnoreCase) && ulong.TryParse(groupKey.Substring(5), out ulong teamId)) {
                RelationshipManager.PlayerTeam team = RelationshipManager.ServerInstance?.FindPlayersTeam(playerId);
                return team != null && team.teamID == teamId;
            }
            if (groupKey.StartsWith("player:", StringComparison.OrdinalIgnoreCase) && ulong.TryParse(groupKey.Substring(7), out ulong ownerId)) {
                return ownerId == playerId || IsSameGroup(ownerId, playerId);
            }
            return false;
        }
        private ulong GetAttackerId(HitInfo info) {
            BasePlayer player = info?.InitiatorPlayer;
            if (player != null && !player.IsNpc && player.userID.IsSteamId()) return player.userID;
            ulong userId = GetEntityPlayerId(info?.Initiator);
            if (userId.IsSteamId()) return userId;
            userId = GetEntityPlayerId(info?.Weapon);
            if (userId.IsSteamId()) return userId;
            return 0;
        }
        private ulong GetEntityPlayerId(BaseEntity entity) {
            HashSet<BaseEntity> visited = null;
            for (int depth = 0; entity != null && depth < 8; depth++) {
                if (visited == null) visited = new HashSet<BaseEntity>();
                if (!visited.Add(entity)) {
                    return 0;
                }
                BasePlayer player = entity.ToPlayer();
                if (player != null && !player.IsNpc && player.userID.IsSteamId()) return player.userID;
                if (entity.OwnerID.IsSteamId()) return entity.OwnerID;
                entity = entity.creatorEntity;
            }
            return 0;
        }
        private string GetEntityId(BaseNetworkable entity) {
            return entity?.net == null ? "0" : entity.net.ID.Value.ToString();
        }
        private string EntityText(BaseEntity entity) {
            if (entity == null) return "null";
            return $"{entity.ShortPrefabName}/{entity.OwnerID}/{GetEntityPlayerId(entity)}";
        }
        private string HitInfoText(HitInfo info) {
            if (info == null) return "null";
            string damage = info.damageTypes == null ? "null" : $"{info.damageTypes.GetMajorityDamageType()}:{info.damageTypes.Total():0.0}";
            return $"initiator={EntityText(info.Initiator)} initiatorPlayer={(info.InitiatorPlayer == null ? 0 : info.InitiatorPlayer.userID)} weapon={EntityText(info.Weapon)} weaponPrefab={EntityText(info.WeaponPrefab)} damage={damage}";
        }
        private bool HasScorableGear(BasePlayer player) {
            if (player?.inventory == null) return false;
            return HasScorableItem(player.inventory.containerBelt) || HasScorableItem(player.inventory.containerMain) || HasScorableItem(player.inventory.containerWear);
        }
        private bool HasScorableItem(ItemContainer container) {
            if (container?.itemList == null) return false;
            foreach (Item item in container.itemList) {
                if (item?.info == null) continue;
                string shortname = item.info.shortname;
                if (shortname == "rock" || shortname == "torch") continue;
                if (item.info.category == ItemCategory.Weapon || item.info.category == ItemCategory.Tool || item.info.category == ItemCategory.Attire) return true;
            }
            return false;
        }
        private string GetCurrentPhase() {
            string phase = NormalizePhase(GetPluginPhase(FBuildZoneStages));
            if (!string.IsNullOrEmpty(phase)) return phase;
            phase = GetPluginPhase(Stadia);
            return NormalizePhase(phase);
        }
        private bool IsRaidPhase() {
            string phase = NormalizePhase(GetPluginPhase(FBuildZoneStages));
            if (!string.IsNullOrEmpty(phase)) return IsRaidPhaseName(phase);
            return IsRaidPhaseName(GetPluginPhase(Stadia));
        }
        private string GetPluginPhase(Plugin plugin) {
            object result = plugin?.Call("GetCurrentPhase");
            return result == null ? string.Empty : result.ToString();
        }
        private bool IsRaidPhaseName(string phase) {
            phase = NormalizePhase(phase);
            return phase == "raid" || phase == "phase_raid" || phase == "raidblock" || phase == "raid_block" || phase == "phase_raidblock" || phase == "phase_raid_block";
        }
        private string NormalizePhase(string phase) {
            return string.IsNullOrEmpty(phase) ? string.Empty : phase.Trim().ToLowerInvariant();
        }
        private bool IsCupboardEntity(BaseEntity entity) {
            if (entity == null) return false;
            if (entity is BuildingPrivlidge) return true;
            string shortName = entity.ShortPrefabName;
            if (!string.IsNullOrEmpty(shortName) && shortName.IndexOf("cupboard.tool", StringComparison.OrdinalIgnoreCase) >= 0) return true;
            string prefabName = entity.PrefabName;
            return !string.IsNullOrEmpty(prefabName) && prefabName.IndexOf("cupboard.tool", StringComparison.OrdinalIgnoreCase) >= 0;
        }
        private BuildingPrivlidge GetCupboardPrivilege(BaseEntity entity) {
            return entity as BuildingPrivlidge;
        }
        private void ScanCupboardClans() {
            foreach (BaseNetworkable entity in BaseNetworkable.serverEntities) {
                BuildingPrivlidge priv = entity as BuildingPrivlidge;
                if (priv == null || priv.IsDestroyed) continue;
                RememberCupboardState(priv);
            }
        }
        private CupboardEntry RememberCupboardState(BuildingPrivlidge priv) {
            if (priv?.net == null) return null;
            if (!_cupboardEntries.TryGetValue(priv.net.ID, out CupboardEntry entry)) {
                entry = new CupboardEntry();
                _cupboardEntries[priv.net.ID] = entry;
            }
            entry.OwnerId = priv.OwnerID;
            entry.ClanTag = GetLiveCupboardClanTag(priv);
            entry.GroupKey = GetCupboardGroupKey(priv);
            entry.UserIds.Clear();
            if (entry.OwnerId.IsSteamId()) entry.UserIds.Add(entry.OwnerId);
            if (priv.authorizedPlayers != null) {
                foreach (ulong userId in priv.authorizedPlayers) {
                    if (userId.IsSteamId()) entry.UserIds.Add(userId);
                }
            }
            FillGroupUsers(entry.GroupKey, entry.UserIds);
            if (string.IsNullOrEmpty(entry.ClanTag)) {
                foreach (ulong userId in entry.UserIds) {
                    string userClan = GetClanTag(userId);
                    if (!string.IsNullOrEmpty(userClan)) {
                        entry.ClanTag = userClan;
                        break;
                    }
                }
            }
            string clan = entry.ClanTag;
            if (!string.IsNullOrEmpty(clan)) _cupboardClanTags[priv.net.ID] = clan;
            return entry;
        }
        private string GetCupboardClanTag(BuildingPrivlidge priv) {
            return GetCupboardClanTag(priv, null);
        }
        private string GetCupboardClanTag(BuildingPrivlidge priv, CupboardEntry cupboard) {
            if (!string.IsNullOrEmpty(cupboard?.ClanTag)) return cupboard.ClanTag;
            if (priv?.net != null && _cupboardClanTags.TryGetValue(priv.net.ID, out string stored) && !string.IsNullOrEmpty(stored)) return stored;
            return GetLiveCupboardClanTag(priv);
        }
        private string GetLiveCupboardClanTag(BuildingPrivlidge priv) {
            Dictionary<string, object> info = FBuildZoneStages?.Call("GetCupboardInfo", priv) as Dictionary<string, object>;
            if (info != null && info.TryGetValue("clanTag", out object value)) {
                string tag = value as string;
                if (!string.IsNullOrEmpty(tag)) return tag;
            }
            if (priv == null) return string.Empty;
            string clan = GetClanTag(priv.OwnerID);
            if (!string.IsNullOrEmpty(clan)) return clan;
            if (priv.authorizedPlayers != null) {
                foreach (ulong userId in priv.authorizedPlayers) {
                    clan = GetClanTag(userId);
                    if (!string.IsNullOrEmpty(clan)) return clan;
                }
            }
            return string.Empty;
        }
        private HashSet<string> GetCupboardClanTags(BuildingPrivlidge priv) {
            HashSet<string> clans = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
            Dictionary<string, object> info = FBuildZoneStages?.Call("GetCupboardInfo", priv) as Dictionary<string, object>;
            if (info != null && info.TryGetValue("clanTag", out object value)) {
                string tag = value as string;
                if (!string.IsNullOrEmpty(tag)) clans.Add(tag);
            }
            if (priv == null) return clans;
            string clan = GetClanTag(priv.OwnerID);
            if (!string.IsNullOrEmpty(clan)) clans.Add(clan);
            if (priv.authorizedPlayers != null) {
                foreach (ulong userId in priv.authorizedPlayers) {
                    clan = GetClanTag(userId);
                    if (!string.IsNullOrEmpty(clan)) clans.Add(clan);
                }
            }
            return clans;
        }
        private void BanCupboardVictims(BuildingPrivlidge priv, string clanTag, CupboardEntry cupboard) {
            if (!string.IsNullOrEmpty(clanTag)) {
                int banned = BanClan(clanTag);
                if (banned > 0) return;
            }
            HashSet<ulong> users = GetCupboardUserIds(priv, cupboard);
            if (users.Count == 0) {
                return;
            }
            long until = GetNow() + RaidBanSeconds;
            foreach (ulong userId in users) {
                if (!userId.IsSteamId()) continue;
                BanPlayer(userId, until);
            }
            SaveRaidBans();
        }
        private int BanClan(string clanTag) {
            List<string> members = GetClanMembers(clanTag);
            if (members == null || members.Count == 0) {
                return 0;
            }
            int count = 0;
            long until = GetNow() + RaidBanSeconds;
            foreach (string member in members) {
                if (!ulong.TryParse(member, out ulong userId) || !userId.IsSteamId()) continue;
                BanPlayer(userId, until);
                count++;
            }
            SaveRaidBans();
            return count;
        }
        private HashSet<ulong> GetCupboardUserIds(BuildingPrivlidge priv) {
            return GetCupboardUserIds(priv, null);
        }
        private HashSet<ulong> GetCupboardUserIds(BuildingPrivlidge priv, CupboardEntry cupboard) {
            HashSet<ulong> users = new HashSet<ulong>();
            if (cupboard != null) {
                foreach (ulong userId in cupboard.UserIds) {
                    if (userId.IsSteamId()) users.Add(userId);
                }
            }
            if (priv != null) {
                if (priv.OwnerID.IsSteamId()) users.Add(priv.OwnerID);
                if (priv.authorizedPlayers != null) {
                    foreach (ulong userId in priv.authorizedPlayers) {
                        if (userId.IsSteamId()) users.Add(userId);
                    }
                }
            }
            string groupKey = string.IsNullOrEmpty(cupboard?.GroupKey) ? GetCupboardGroupKey(priv) : cupboard.GroupKey;
            FillGroupUsers(groupKey, users);
            return users;
        }
        private void FillGroupUsers(string groupKey, HashSet<ulong> users) {
            if (string.IsNullOrEmpty(groupKey) || users == null) return;
            if (groupKey.StartsWith("player:", StringComparison.OrdinalIgnoreCase) && ulong.TryParse(groupKey.Substring(7), out ulong ownerId) && ownerId.IsSteamId()) {
                users.Add(ownerId);
            }
            else if (groupKey.StartsWith("team:", StringComparison.OrdinalIgnoreCase) && ulong.TryParse(groupKey.Substring(5), out ulong teamId)) {
                RelationshipManager.PlayerTeam team = RelationshipManager.ServerInstance?.FindTeam(teamId);
                if (team != null && team.members != null) {
                    foreach (ulong userId in team.members) {
                        if (userId.IsSteamId()) users.Add(userId);
                    }
                }
            }
            else if (groupKey.StartsWith("clan:", StringComparison.OrdinalIgnoreCase)) {
                foreach (string member in GetClanMembers(groupKey.Substring(5))) {
                    if (ulong.TryParse(member, out ulong userId) && userId.IsSteamId()) users.Add(userId);
                }
            }
        }
        private string GetCupboardGroupKey(BuildingPrivlidge priv) {
            Dictionary<string, object> info = FBuildZoneStages?.Call("GetCupboardInfo", priv) as Dictionary<string, object>;
            if (info == null || !info.TryGetValue("groupKey", out object value)) return string.Empty;
            string key = value as string;
            return key ?? string.Empty;
        }
        private List<string> GetClanMembers(string clanTag) {
            object result = SClan?.Call("GetMembersClan", clanTag);
            if (result is List<string> typed) return typed;
            if (result is List<object> objects) {
                List<string> members = new List<string>();
                foreach (object value in objects) {
                    if (value != null) members.Add(value.ToString());
                }
                return members;
            }
            return new List<string>();
        }
        private void BanPlayer(ulong userId, long until) {
            ServerUsers.User current = ServerUsers.Get(userId);
            if (current != null && current.group == ServerUsers.UserGroup.Banned && current.notes != RaidBanReason && (current.expiry <= 0 || current.expiry > until)) {
                return;
            }
            _raidBans[userId] = until;
            BasePlayer player = BasePlayer.FindAwakeOrSleepingByID(userId);
            string name = player == null ? userId.ToString() : player.displayName;
            ServerUsers.Set(userId, ServerUsers.UserGroup.Banned, name, RaidBanReason, until);
            ServerUsers.Save();
            if (player != null && player.IsConnected) {
                player.Kick("Ваш клан зарейдили. Бан на 3 часа.");
            }
            ScheduleUnban(userId, until);
        }
        private void LoadRaidBans() {
            _raidBans.Clear();
            try {
                Dictionary<ulong, long> stored = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, long>>(RaidBanData);
                if (stored == null) return;
                foreach (KeyValuePair<ulong, long> entry in stored) {
                    _raidBans[entry.Key] = entry.Value;
                }
            }
            catch {
            }
        }
        private void SaveRaidBans() {
            Interface.Oxide.DataFileSystem.WriteObject(RaidBanData, _raidBans);
        }
        private void ScheduleRaidBans() {
            List<ulong> users = new List<ulong>(_raidBans.Keys);
            foreach (ulong userId in users) {
                if (!_raidBans.TryGetValue(userId, out long until)) continue;
                if (until <= GetNow()) UnbanPlayer(userId);
                else ScheduleUnban(userId, until);
            }
        }
        private void ScheduleUnban(ulong userId, long until) {
            float seconds = until - GetNow();
            if (seconds < 1f) seconds = 1f;
            timer.Once(seconds, () => UnbanPlayer(userId));
        }
        private void UnbanPlayer(ulong userId) {
            if (_raidBans.TryGetValue(userId, out long until) && until > GetNow()) {
                ScheduleUnban(userId, until);
                return;
            }
            _raidBans.Remove(userId);
            ServerUsers.User current = ServerUsers.Get(userId);
            if (current != null && current.group == ServerUsers.UserGroup.Banned && current.notes == RaidBanReason) {
                ServerUsers.Remove(userId);
                ServerUsers.Save();
            }
            SaveRaidBans();
        }
        private long GetNow() {
            return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
        }
        private void CreateUI(BasePlayer player) {
            if (player == null || !player.IsConnected || player.IsNpc) {
                return;
            }
            CuiHelper.DestroyUi(player, UiRoot);
            var container = new CuiElementContainer();
            container.Add(new CuiElement {
                Name = UiRoot, Parent = "Hud", Components = {
                    new CuiRectTransformComponent {
                        AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0"
                    }
                }
            }
            );
            AddFrame(container);
            AddHeaders(container);
            AddRows(container, GetClanRows());
            CuiHelper.AddUi(player, container);
        }
        private void AddFrame(CuiElementContainer container) {
            container.Add(new CuiElement {
                Name = "Hudaima_Leaders_Path_2", Parent = UiRoot, Components = {
                    new CuiRawImageComponent {
                        Color = "1 1 1 1", Png = Img("Hudaima_Leaders_Path_2")
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = "-160.0000 -202.0000", OffsetMax = "-20.0000 -33.3333"
                    }
                }
            }
            );
            container.Add(new CuiElement {
                Name = "Hudaima_Leaders_Header_Backplate_1", Parent = UiRoot, Components = {
                    new CuiRawImageComponent {
                        Color = "1 1 1 1", Png = Img("Hudaima_Leaders_Header_Backplate_1")
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = "-160.0000 -47.3333", OffsetMax = "-20.0000 -19.3333"
                    }
                }
            }
            );
        }
        private void AddHeaders(CuiElementContainer container) {
            container.Add(new CuiElement {
                Name = "Hudaima_Leaders_Title_Text_1", Parent = UiRoot, Components = {
                    new CuiTextComponent {
                        Text = "LEADERS", FontSize = 13, Align = TextAnchor.MiddleLeft, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf"
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = "-109.3333 -41.3333", OffsetMax = "-36.0000 -25.3333"
                    }
                }
            }
            );
            container.Add(new CuiElement {
                Name = "Hudaima_Leaders_Rank_Header_Text_1", Parent = UiRoot, Components = {
                    new CuiTextComponent {
                        Text = "#", FontSize = 7, Align = TextAnchor.MiddleCenter, Color = "0.722 0.722 0.722 1", Font = "robotocondensed-bold.ttf"
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = "-152.0000 -68.0000", OffsetMax = "-137.3333 -56.0000"
                    }
                }
            }
            );
            container.Add(new CuiElement {
                Name = "Hudaima_Leaders_Team_Header_Text_1", Parent = UiRoot, Components = {
                    new CuiTextComponent {
                        Text = "TEAM", FontSize = 7, Align = TextAnchor.MiddleLeft, Color = "0.722 0.722 0.722 1", Font = "robotocondensed-bold.ttf"
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = "-130.6667 -68.0000", OffsetMax = "-104.0000 -56.0000"
                    }
                }
            }
            );
            container.Add(new CuiElement {
                Name = "Hudaima_Leaders_Points_Header_Text_1", Parent = UiRoot, Components = {
                    new CuiTextComponent {
                        Text = "POINTS", FontSize = 7, Align = TextAnchor.MiddleRight, Color = "0.722 0.722 0.722 1", Font = "robotocondensed-bold.ttf"
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = "-72.0000 -68.0000", OffsetMax = "-34.6667 -56.0000"
                    }
                }
            }
            );
        }
        private void AddRows(CuiElementContainer container, List<ClanRow> rows) {
            var count = rows.Count < MaxRows ? rows.Count : MaxRows;
            for (var i = 0; i < count; i++) {
                AddRow(container, i + 1, rows[i]);
            }
        }
        private void AddRow(CuiElementContainer container, int place, ClanRow row) {
            var index = place - 1;
            var badgeMinY = -84f - index * 18f;
            var badgeMaxY = -72f - index * 18f;
            var textMinY = -84.6667f - index * 18f;
            var textMaxY = -71.3333f - index * 18f;
            var valueMinY = -86f - index * 18f;
            var valueMaxY = -70f - index * 18f;
            if (place == 7) {
                badgeMinY = -192.6667f;
                badgeMaxY = -180.6667f;
                textMinY = -193.3333f;
                textMaxY = -180f;
                valueMinY = -194.6667f;
                valueMaxY = -178.6667f;
            }
            var color = place == 1 ? "1.000 0.925 0.275 1" : "0.925 0.925 0.925 1";
            container.Add(new CuiElement {
                Name = $"Hudaima_Leaders_Rank_{place}_Badge_1", Parent = UiRoot, Components = {
                    new CuiRawImageComponent {
                        Color = "1 1 1 1", Png = Img("Hudaima_Leaders_Rank_1_Badge_1")
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = string.Format(CultureInfo.InvariantCulture, "-150.6667 {0:0.####}", badgeMinY), OffsetMax = string.Format(CultureInfo.InvariantCulture, "-138.6667 {0:0.####}", badgeMaxY)
                    }
                }
            }
            );
            container.Add(new CuiElement {
                Name = $"Hudaima_Leaders_Rank_{place}_Text_1", Parent = UiRoot, Components = {
                    new CuiTextComponent {
                        Text = place.ToString(), FontSize = 7, Align = TextAnchor.MiddleCenter, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf"
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "1.0000 1.0000", AnchorMax = "1.0000 1.0000", OffsetMin = string.Format(CultureInfo.InvariantCulture, "-152.0000 {0:0.####}", textMinY), OffsetMax = string.Format(CultureInfo.InvariantCulture, "-137.3333 {0:0.####}", textMaxY)
                    }
                }
            }
            );
            container.Add(new CuiElement {
                Name = $"Hudaima_Leaders_Team_{place}_Text_1", Parent = UiRoot, Components = {
                    new CuiTextComponent {
                        Text = row.Tag.ToUpperInvariant(), FontSize = 11, Align = TextAnchor.MiddleLeft, Color = color, Font = "robotocondensed-bold.ttf"
 
// ... [Code preview truncated due to length. Full source in attached file] ...

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