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

FREE Clans : 3.0.39 3.0.39

Нет прав для скачивания
C#:
using CompanionServer;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using ProtoBuf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using VersionNumber = Oxide.Core.VersionNumber;
namespace Oxide.Plugins {
    [Info("Clans", "k1lly0u", "3.0.39")]
    class Clans : RustPlugin {
#region Fields
        [PluginReference]
        private Plugin DiscordClans;
        internal StoredData storedData;
        private bool wipeData;
        private bool isInitialized = false;
        private Coroutine initClansRoutine;
        private Regex tagFilter;
        private Regex hexFilter;
        private int[] customTagMinValue;
        private int[] customTagMaxValue;
        private HashSet<ulong> friendlyFireDisabled = new HashSet<ulong>();
        public static Clans Instance {
            get;
            private set;
        }
        private static DateTime Epoch = new DateTime(1970, 1, 1);
        private static double MaxUnixSeconds = (DateTime.MaxValue - Epoch).TotalSeconds;
        private const string COLORED_LABEL = "<color={0}>{1}</color>";
        private enum MessageType {
            Create, Invite, InviteReject, InviteWithdrawn, Join, Leave, Kick, Promote, Demote, Disband, AllianceInvite, AllianceInviteReject, AllianceInviteWithdrawn, AllianceAccept, AllianceWithdrawn, TeamChat, ClanChat, AllyChat
        }
#endregion
#region Oxide Hooks
        private void Loaded() {
            Instance = this;
            permission.RegisterPermission(configData.Permissions.PermissionCreate, this);
            permission.RegisterPermission(configData.Permissions.PermissionJoin, this);
            permission.RegisterPermission(configData.Permissions.PermissionLeave, this);
            permission.RegisterPermission(configData.Permissions.PermissionDisband, this);
            permission.RegisterPermission(configData.Permissions.PermissionKick, this);
            permission.RegisterPermission(configData.Permissions.ClanInfoPermission, this);
            lang.RegisterMessages(Messages, this);
            cmd.AddChatCommand(configData.Commands.FFCommand, this, cmdClanFF);
            cmd.AddChatCommand(configData.Commands.AFFCommand, this, cmdAllyFF);
            cmd.AddChatCommand(configData.Commands.ClanCommand, this, cmdChatClan);
            cmd.AddChatCommand(configData.Commands.AllyChatCommand, this, cmdAllianceChat);
            cmd.AddChatCommand(configData.Commands.ClanChatCommand, this, cmdClanChat);
            cmd.AddChatCommand(configData.Commands.ClanInfoCommand, this, cmdChatClanInfo);
            cmd.AddChatCommand(configData.Commands.ClanHelpCommand, this, cmdChatClanHelp);
            cmd.AddChatCommand(configData.Commands.ClanAllyCommand, this, cmdChatClanAlly);
            _tags.Add(new KeyValuePair<string, string>(configData.Tags.TagOpen, configData.Tags.TagClose));
            tagFilter = new Regex($"[^a-zA-Z0-9{configData.Tags.AllowedCharacters}]");
            hexFilter = new Regex("^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
            SetMinMaxColorRange();
            if (!configData.Tags.EnabledBC) Unsubscribe(nameof(OnPluginLoaded));
            if (!configData.Clans.MemberFF && !configData.Clans.Alliance.AllyFF) Unsubscribe(nameof(OnEntityTakeDamage));
            if (configData.Clans.Teams.Enabled) RelationshipManager.maxTeamSize = configData.Clans.MemberLimit;
            LoadData();
        }
        private void OnServerInitialized() {
            initClansRoutine = ServerMgr.Instance.StartCoroutine(InitializeClans());
        }
        private void OnNewSave(string str) => wipeData = configData.Purge.WipeOnNewSave;
        private void OnServerSave() => SaveData();
        private void OnPluginLoaded(Plugin plugin) {
            if (configData.Tags.EnabledBC && plugin?.Title == "Better Chat") Interface.CallHook("API_RegisterThirdPartyTitle", this, new Func<Oxide.Core.Libraries.Covalence.IPlayer, string>(BetterChat_FormattedClanTag));
        }
        private void OnPlayerConnected(BasePlayer player) {
            if (player.currentTeam != 0UL) {
                if (configData.Clans.Teams.Enabled) {
                    player.ClearTeam();
                    RelationshipManager.ServerInstance.playerToTeam.Remove(player.userID);
                }
                else {
                    RelationshipManager.PlayerTeam playerTeam = RelationshipManager.ServerInstance.FindTeam(player.currentTeam);
                    if (playerTeam == null || !playerTeam.members.Contains(player.userID)) {
                        player.ClearTeam();
                        RelationshipManager.ServerInstance.playerToTeam.Remove(player.userID);
                    }
                }
            }
            Clan clan = storedData?.FindClanByID(player.userID);
            if (clan != null) {
                clan.OnPlayerConnected(player);
            }
            else {
                List<string> invites;
                if (storedData.playerInvites.TryGetValue(player.userID, out invites)) {
                    player.ChatMessage(string.Format(msg("Notification.PendingInvites", player.UserIDString), invites.ToSentence(), configData.Commands.ClanCommand));
                }
            }
        }
        private void OnPlayerDisconnected(BasePlayer player) => storedData?.FindClanByID(player.userID)?.OnPlayerDisconnected(player);
        private object OnPlayerChat(BasePlayer player, string message, ConVar.Chat.ChatChannel channel) {
            if (channel != ConVar.Chat.ChatChannel.Team) return null;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) return null;
            if (configData.Options.DenyOnMuted) {
                object success = Interface.CallHook("API_IsMuted", player.IPlayer);
                if ((success is bool && (bool)success) || player.HasPlayerFlag(BasePlayer.PlayerFlags.ChatMute)) {
                    player.ChatMessage(msg("Chat.IsMuted", player.UserIDString));
                    return false;
                }
            }
            Instance.DiscordClans?.CallHook("LogMessage", $"{player.displayName} : {message}", (int)MessageType.TeamChat);
            Interface.CallHook("OnClanChat", player, message, clan.Tag);
            return null;
        }
        private object OnTeamCreate(BasePlayer player) {
            if (!configData.Clans.Teams.Enabled) return null;
            player.ChatMessage(msg("Notification.Create.NoNativeCreate", player.UserIDString));
            return true;
        }
        private object OnTeamKick(RelationshipManager.PlayerTeam playerTeam, BasePlayer player, ulong targetId) {
            if (!configData.Clans.Teams.Enabled || string.IsNullOrEmpty(playerTeam.teamName)) return null;
            if (!configData.Clans.Teams.AllowKick) return false;
            KickPlayer(player, targetId);
            return true;
        }
        private object OnTeamInvite(BasePlayer player, BasePlayer other) {
            if (!configData.Clans.Teams.Enabled) return null;
            if (!configData.Clans.Teams.AllowInvite) return false;
            if (other.IsNpc || other != null && !other.userID.IsSteamId()) return false;
            InvitePlayer(player, other);
            return true;
        }
        private object OnTeamAcceptInvite(RelationshipManager.PlayerTeam playerTeam, BasePlayer player) {
            if (!configData.Clans.Teams.Enabled || string.IsNullOrEmpty(playerTeam.teamName)) return null;
            JoinClan(player, playerTeam.teamName);
            return true;
        }
        private object OnTeamRejectInvite(BasePlayer player, RelationshipManager.PlayerTeam playerTeam) {
            if (!configData.Clans.Teams.Enabled || string.IsNullOrEmpty(playerTeam.teamName)) return null;
            RejectInvite(player, playerTeam.teamName);
            return true;
        }
        private object OnTeamLeave(RelationshipManager.PlayerTeam playerTeam, BasePlayer player) {
            if (!configData.Clans.Teams.Enabled || string.IsNullOrEmpty(playerTeam.teamName)) return null;
            if (!configData.Clans.Teams.AllowLeave) return false;
            LeaveClan(player);
            return true;
        }
        private object OnTeamPromote(RelationshipManager.PlayerTeam playerTeam, BasePlayer player) {
            if (!configData.Clans.Teams.Enabled || string.IsNullOrEmpty(playerTeam.teamName)) return null;
            if (!configData.Clans.Teams.AllowPromote) return false;
            PromotePlayer(BasePlayer.FindByID(playerTeam.teamLeader), player.userID);
            return true;
        }
        private object OnTeamDisband(RelationshipManager.PlayerTeam playerTeam) {
            if (!configData.Clans.Teams.Enabled || string.IsNullOrEmpty(playerTeam.teamName)) return null;
            Clan clan = storedData.FindClan(playerTeam.teamName);
            if (clan != null) clan.DisbandClan();
            return true;
        }
        private object OnEntityTakeDamage(BasePlayer player, HitInfo info) {
            if (!player || !info?.InitiatorPlayer) return null;
            if (player == info.InitiatorPlayer) return null;
            Clan victimClan = storedData.FindClanByID(player.userID);
            if (victimClan == null) return null;
            Clan attackerClan = storedData.FindClanByID(info.InitiatorPlayer.userID);
            if (attackerClan == null) return null;
            Clan.Member member = storedData.FindMemberByID(info.InitiatorPlayer.userID);
            if (member == null) return null;
            if (friendlyFireDisabled.Contains(player.userID)) return null;
            if (victimClan.Tag.Equals(attackerClan.Tag) && configData.Clans.MemberFF && member.MemberFFEnabled) {
                member.OnClanMemberHit(string.Format(COLORED_LABEL, victimClan.GetRoleColor(player.userID), player.displayName));
                return true;
            }
            if (victimClan.IsAlliedClan(attackerClan.Tag) && configData.Clans.Alliance.Enabled && configData.Clans.Alliance.AllyFF && member.AllyFFEnabled) {
                member.OnAllyMemberHit(string.Format(COLORED_LABEL, victimClan.GetRoleColor(player.userID), player.displayName));
                return true;
            }
            return null;
        }
        private void Unload() {
            if (isInitialized) {
                SaveData();
                foreach (Clan clan in storedData.clans.Values) clan.OnUnload();
            }
            else {
                if (initClansRoutine != null) ServerMgr.Instance.StopCoroutine(initClansRoutine);
            }
            configData = null;
            Instance = null;
        }
#endregion
#region Functions
        private IEnumerator InitializeClans() {
            Puts("Initializing Clans...");
            if (configData.Clans.Teams.Enabled) {
                RelationshipManager.ServerInstance.playerToTeam.Clear();
                foreach(KeyValuePair<ulong, RelationshipManager.PlayerTeam> kvp in RelationshipManager.ServerInstance.teams) {
                    RelationshipManager.PlayerTeam playerTeam = kvp.Value;
                    ClearTeam(ref playerTeam);
                }
                RelationshipManager.ServerInstance.teams.Clear();
                RelationshipManager.ServerInstance.lastTeamIndex = 1;
            }
            if (wipeData) {
                storedData.clans.Clear();
                storedData.playerInvites.Clear();
                SaveData();
            }
            else {
                List<string> purgedClans = Facepunch.Pool.Get<List<string>>();
                foreach (KeyValuePair<string, Clan> kvp in storedData.clans) {
                    Clan clan = kvp.Value;
                    if (clan.ClanMembers.Count == 0 || (configData.Purge.Enabled && UnixTimeStampUTC() - clan.LastOnlineTime > (configData.Purge.OlderThanDays * 86400))) {
                        purgedClans.Add(kvp.Key);
                        continue;
                    }
                    clan.Description = StripHTMLTags(clan.Description);
                    if (configData.Clans.Alliance.Enabled) {
                        for (int i = clan.AllianceInvites.Count - 1; i >= 0; i--) {
                            KeyValuePair<string, double> allianceInvite = clan.AllianceInvites.ElementAt(i);
                            if (!storedData.clans.ContainsKey(allianceInvite.Key) || (UnixTimeStampUTC() - allianceInvite.Value > configData.Clans.Invites.AllianceInviteExpireTime)) clan.AllianceInvites.Remove(allianceInvite.Key);
                        }
                        for (int i = clan.Alliances.Count - 1; i >= 0; i--) {
                            string allyTag = clan.Alliances.ElementAt(i);
                            if (!storedData.clans.ContainsKey(allyTag)) clan.Alliances.Remove(allyTag);
                        }
                    }
                    for (int i = clan.MemberInvites.Count - 1; i >= 0; i--) {
                        KeyValuePair<ulong, Clan.MemberInvite> memberInvite = clan.MemberInvites.ElementAt(i);
                        if (UnixTimeStampUTC() - memberInvite.Value.ExpiryTime > configData.Clans.Invites.MemberInviteExpireTime) clan.MemberInvites.Remove(memberInvite.Key);
                    }
                    foreach (KeyValuePair<ulong, Clan.Member> member in clan.ClanMembers) storedData.RegisterPlayer(member.Key, clan.Tag);
                    if (configData.Permissions.PermissionGroups) permission.CreateGroup(configData.Permissions.PermissionGroupPrefix + clan.Tag, "Clan " + clan.Tag, 0);
                    yield return null;
                }
                if (purgedClans.Count > 0) {
                    Puts($"Purging {purgedClans.Count} expired or invalid clans");
                    StringBuilder str = new StringBuilder();
                    for (int i = 0; i < purgedClans.Count; i++) {
                        string tag = purgedClans[i];
                        Clan clan = storedData.clans[tag];
                        if (clan == null) continue;
                        permission.RemoveGroup(configData.Permissions.PermissionGroupPrefix + clan.Tag);
                        str.Append($"{(i > 0 ? "\n" : "")}Purged - [{tag}] | {clan.Description} | Owner: {clan.OwnerID} | Last Online: {UnixTimeStampToDateTime(clan.LastOnlineTime)}");
                        storedData.clans.Remove(tag);
                    }
                    if (configData.Purge.ListPurgedClans) {
                        Puts(str.ToString());
                        if (configData.Options.LogChanges) LogToFile(Title, str.ToString(), this);
                    }
                }
                Puts($"Loaded {storedData.clans.Count} clans!");
                Facepunch.Pool.FreeUnmanaged(ref purgedClans);
            }
            if (configData.Tags.EnabledBC) Interface.CallHook("API_RegisterThirdPartyTitle", this, new Func<Oxide.Core.Libraries.Covalence.IPlayer, string>(BetterChat_FormattedClanTag));
            isInitialized = true;
            initClansRoutine = null;
            foreach (BasePlayer player in BasePlayer.activePlayerList) OnPlayerConnected(player);
        }
#endregion
#region Clan Tag Colors
        private void SetMinMaxColorRange() {
            customTagMinValue = new int[3];
            customTagMaxValue = new int[3];
            if (configData.Tags.CustomTagColorMin.StartsWith("#")) configData.Tags.CustomTagColorMin = configData.Tags.CustomTagColorMin.Substring(1);
            if (configData.Tags.CustomTagColorMax.StartsWith("#")) configData.Tags.CustomTagColorMax = configData.Tags.CustomTagColorMax.Substring(1);
            customTagMinValue[0] = int.Parse(configData.Tags.CustomTagColorMin.Substring(0, 2), NumberStyles.AllowHexSpecifier);
            customTagMinValue[1] = int.Parse(configData.Tags.CustomTagColorMin.Substring(2, 2), NumberStyles.AllowHexSpecifier);
            customTagMinValue[2] = int.Parse(configData.Tags.CustomTagColorMin.Substring(3, 2), NumberStyles.AllowHexSpecifier);
            customTagMaxValue[0] = int.Parse(configData.Tags.CustomTagColorMax.Substring(0, 2), NumberStyles.AllowHexSpecifier);
            customTagMaxValue[1] = int.Parse(configData.Tags.CustomTagColorMax.Substring(2, 2), NumberStyles.AllowHexSpecifier);
            customTagMaxValue[2] = int.Parse(configData.Tags.CustomTagColorMax.Substring(3, 2), NumberStyles.AllowHexSpecifier);
        }
        private bool TagColorIsBlocked(string color) {
            if (color.StartsWith("#")) color = color.Substring(1);
            if (configData.Tags.BlockedTagColors.Contains(color, StringComparer.OrdinalIgnoreCase)) return true;
            return false;
        }
        private bool TagColorWithinRange(string color) {
            if (color.StartsWith("#")) color = color.Substring(1);
            int red = int.Parse(color.Substring(0, 2), NumberStyles.AllowHexSpecifier);
            int green = int.Parse(color.Substring(2, 2), NumberStyles.AllowHexSpecifier);
            int blue = int.Parse(color.Substring(4, 2), NumberStyles.AllowHexSpecifier);
            return red >= customTagMinValue[0] && red <= customTagMaxValue[0] && green >= customTagMinValue[1] && green <= customTagMaxValue[1] && blue >= customTagMinValue[2] && blue <= customTagMaxValue[2];
        }
#endregion
#region Helpers
        private string BetterChat_FormattedClanTag(Oxide.Core.Libraries.Covalence.IPlayer player) {
            Clan clan = storedData.FindClanByID(player.Id);
            if (clan == null) return string.Empty;
            string tagColor = string.IsNullOrEmpty(clan.TagColor) || !configData.Tags.CustomColors ? configData.Tags.TagColor : clan.TagColor;
            if (configData.Tags.EnabledGroupColors && (string.IsNullOrEmpty(clan.TagColor) || !configData.Tags.CustomColors)) {
                foreach (KeyValuePair<string, string> kvp in configData.Tags.GroupTagColors) {
                    if (player.BelongsToGroup(kvp.Key)) {
                        tagColor = kvp.Value;
                        break;
                    }
                }
            }
            return $"[#{tagColor.Replace("#", "")}][+{configData.Tags.TagSize}]{configData.Tags.TagOpen}{clan.Tag}{configData.Tags.TagClose}[/+][/#]";
        }
        private static int UnixTimeStampUTC() => (int)DateTime.UtcNow.Subtract(Epoch).TotalSeconds;
        private static DateTime UnixTimeStampToDateTime(double unixTimeStamp) {
            return unixTimeStamp > MaxUnixSeconds ? Epoch.AddMilliseconds(unixTimeStamp) : Epoch.AddSeconds(unixTimeStamp);
        }
        private bool ContainsBlockedWord(string tag) {
            for (int i = 0; i < configData.Tags.BlockedWords.Length; i++) {
                if (TranslateLeet(tag).ToLower().Contains(configData.Tags.BlockedWords[i].ToLower())) return true;
            }
            return false;
        }
        private string TranslateLeet(string original) {
            string translated = original;
            foreach (KeyValuePair<string, string> leet in leetTable) translated = translated.Replace(leet.Key, leet.Value);
            return translated;
        }
        private bool ClanTagExists(string tag) {
            ICollection<string> collection = storedData.clans.Keys;
            for (int i = 0; i < collection.Count; i++) {
                if (collection.ElementAt(i).Equals(tag, StringComparison.OrdinalIgnoreCase)) return true;
            }
            return false;
        }
        private static string FormatTime(double time) {
            TimeSpan dateDifference = TimeSpan.FromSeconds((float)time);
            int days = dateDifference.Days;
            int hours = dateDifference.Hours + (days * 24);
            int mins = dateDifference.Minutes;
            int secs = dateDifference.Seconds;
            if (hours > 0) return $"{hours:00}h:{mins:00}m:{secs:00}s";
            if (mins > 0) return $"{mins:00}m:{secs:00}s";
            return $"{secs:00}s";
        }
        private BasePlayer FindPlayer(string partialNameOrID) => BasePlayer.allPlayerList.FirstOrDefault<BasePlayer>((BasePlayer x) => x.displayName.Equals(partialNameOrID, StringComparison.OrdinalIgnoreCase)) ?? BasePlayer.allPlayerList.FirstOrDefault<BasePlayer>((BasePlayer x) => x.displayName.Contains(partialNameOrID, CompareOptions.OrdinalIgnoreCase)) ?? BasePlayer.allPlayerList.FirstOrDefault<BasePlayer>((BasePlayer x) => x.UserIDString == partialNameOrID);
        private static void RemoveFromTeam(RelationshipManager.PlayerTeam playerTeam, BasePlayer player) {
            playerTeam.members.Remove(player.userID);
            RelationshipManager.ServerInstance.playerToTeam.Remove(player.userID);
            player.ClearTeam();
        }
        private static void RemoveFromTeam(RelationshipManager.PlayerTeam playerTeam, ulong playerId) {
            playerTeam.members.Remove(playerId);
            RelationshipManager.ServerInstance.playerToTeam.Remove(playerId);
            RelationshipManager.FindByID(playerId)?.ClearTeam();
        }
        private static void ClearTeam(ref RelationshipManager.PlayerTeam playerTeam) {
            playerTeam.invites.Clear();
            playerTeam.members.Clear();
            playerTeam.onlineMemberConnections.Clear();
            playerTeam.teamID = 0UL;
            playerTeam.teamLeader = 0UL;
            playerTeam.teamName = string.Empty;
            Facepunch.Pool.Free(ref playerTeam);
        }
        private static string RemoveTags(string str) {
            foreach (KeyValuePair<string, string> kvp in _tags) {
                if (str.StartsWith(kvp.Key) && str.Contains(kvp.Value) && str.Length > str.IndexOf(kvp.Value)) {
                    str = str.Substring(str.IndexOf(kvp.Value) + 1).Trim();
                }
            }
            return str;
        }
        private static List<KeyValuePair<string, string>> _tags = new List<KeyValuePair<string, string>> {
            new KeyValuePair<string, string>("[", "]"), new KeyValuePair<string, string>("{", "}"), new KeyValuePair<string, string>("(", ")"), new KeyValuePair<string, string>("<", ">"),
        }
        ;
        public static string StripHTMLTags(string source) {
            char[] array = new char[source.Length];
            int arrayIndex = 0;
            bool inside = false;
            for (int i = 0; i < source.Length; i++) {
                char let = source[i];
                if (let == '<') {
                    inside = true;
                    continue;
                }
                if (let == '>') {
                    inside = false;
                    continue;
                }
                if (!inside) {
                    array[arrayIndex] = let;
                    arrayIndex++;
                }
            }
            return new string(array, 0, arrayIndex);
        }
#endregion
#region Clan Management
        internal void CreateClan(BasePlayer player, string tag, string description) {
            if (!player) return;
            if (storedData.FindClanByID(player.userID) != null) {
                player.ChatMessage(msg("Notification.Create.InExistingClan", player.UserIDString));
                return;
            }
            if (configData.Permissions.UsePermissionCreate && !permission.UserHasPermission(player.UserIDString, configData.Permissions.PermissionCreate)) {
                player.ChatMessage(msg("Notification.Create.NoPermission", player.UserIDString));
                return;
            }
            List<ulong> list;
            if (configData.Tags.ReservedClanTags.TryGetValue(tag, out list)) {
                if (!list.Contains(player.userID)) {
                    player.ChatMessage(string.Format(msg("Notification.Create.TagReserved1", player.UserIDString), tag));
                    return;
                }
            }
            if (tag.Length < configData.Tags.TagLength.Minimum || tag.Length > configData.Tags.TagLength.Maximum) {
                player.ChatMessage(string.Format(msg("Notification.Create.InvalidTagLength", player.UserIDString), configData.Tags.TagLength.Minimum, configData.Tags.TagLength.Maximum));
                return;
            }
            if (tagFilter.IsMatch(tag) || ContainsBlockedWord(tag)) {
                player.ChatMessage(msg("Notification.Create.InvalidCharacters", player.UserIDString));
                return;
            }
            if (ClanTagExists(tag)) {
                player.ChatMessage(msg("Notification.Create.ClanExists", player.UserIDString));
                return;
            }
            if (configData.Clans.Teams.Enabled && player.currentTeam != 0UL) {
                RelationshipManager.PlayerTeam playerTeam = RelationshipManager.ServerInstance.FindTeam(player.currentTeam);
                if (playerTeam != null) RemoveFromTeam(playerTeam, player);
                RelationshipManager.ServerInstance.playerToTeam.Remove(player.userID);
                player.ClearTeam();
            }
            storedData.clans[tag] = new Clan(player, tag, description);
            storedData.RegisterPlayer(player.userID, tag);
            player.ChatMessage(string.Format(msg("Notification.Create.Success", player.UserIDString), tag));
            Interface.CallHook("OnClanCreate", tag);
            if (configData.Options.LogChanges) LogToFile(Title, $"{player.displayName} created the clan [{tag}]", this);
            DiscordClans?.CallHook("LogMessage", $"{player.displayName} has created the clan {tag}", (int)MessageType.Create);
        }
        internal bool InvitePlayer(BasePlayer inviter, ulong targetId) {
            BasePlayer invitee = (covalence.Players.FindPlayerById(targetId.ToString())?.Object as BasePlayer);
            if (!invitee) {
                inviter.ChatMessage(string.Format(msg("Notification.Generic.UnableToFindPlayer", inviter.UserIDString), targetId));
                return false;
            }
            return InvitePlayer(inviter, invitee);
        }
        internal bool InvitePlayer(BasePlayer inviter, BasePlayer invitee) {
            if (!inviter || !invitee) return false;
            if (invitee.IsNpc || !invitee.userID.IsSteamId()) return false;
            Clan clan = storedData.FindClanByID(inviter.userID);
            if (clan == null) {
                inviter.ChatMessage(msg("Notification.Generic.NoClan", inviter.UserIDString));
                return false;
            }
            Clan other = storedData.FindClanByID(invitee.userID);
            if (other != null) {
                inviter.ChatMessage(string.Format(msg("Notification.Invite.InClan", inviter.UserIDString), invitee.displayName));
                return false;
            }
            if (configData.Permissions.UsePermissionJoin && !permission.UserHasPermission(invitee.UserIDString, configData.Permissions.PermissionJoin)) {
                inviter.ChatMessage(msg("Notification.Invite.NoPermission", inviter.UserIDString));
                return false;
            }
            return clan.InvitePlayer(inviter, invitee);
        }
        internal bool WithdrawInvite(BasePlayer player, string partialNameOrID) {
            if (!player) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            if (!clan.IsOwner(player.userID) && !clan.IsModerator(player.userID) && !clan.IsCouncil(player.userID)) {
                player.ChatMessage(msg("Notification.WithdrawInvite.NoPermissions", player.UserIDString));
                return false;
            }
            ulong targetId;
            if (!ulong.TryParse(partialNameOrID, out targetId)) targetId = 0UL;
            foreach(KeyValuePair<ulong, Clan.MemberInvite> invite in clan.MemberInvites) {
                if ((targetId != 0UL && targetId.Equals(invite.Key)) || invite.Value.DisplayName.Contains(partialNameOrID)) {
                    storedData.RevokePlayerInvite(targetId, clan.Tag);
                    clan.MemberInvites.Remove(invite.Key);
                    clan.LocalizedBroadcast("Notification.WithdrawInvite.Success", player.displayName, invite.Value.DisplayName);
                    DiscordClans?.CallHook("LogMessage", $"{player.displayName} has withdrawn a clan invite for {invite.Value.DisplayName}", (int)MessageType.InviteWithdrawn);
                    return true;
                }
            }
            if (configData.Clans.Teams.Enabled) player.ClearPendingInvite();
            player.ChatMessage(string.Format(msg("Notification.WithdrawInvite.UnableToFind", player.UserIDString), partialNameOrID));
            return false;
        }
        internal bool RejectInvite(BasePlayer player, string tag) {
            if (!player) return false;
            Clan clan = storedData.FindClan(tag);
            if (clan == null) {
                player.ChatMessage(string.Format(msg("Notification.Generic.InvalidClan", player.UserIDString), tag));
                return false;
            }
            // Update tag from found clan for case insensitive selection
            tag = clan.Tag;
            if (!clan.MemberInvites.ContainsKey(player.userID)) {
                player.ChatMessage(string.Format(msg("Notification.RejectInvite.InvalidInvite", player.UserIDString), tag));
                return false;
            }
            clan.MemberInvites.Remove(player.userID);
            storedData.OnInviteRejected(player.userID, tag);
            if (configData.Clans.Teams.Enabled) clan.PlayerTeam.RejectInvite(player);
            clan.LocalizedBroadcast("Notification.RejectInvite.Message", player.displayName);
            player.ChatMessage(string.Format(msg("Notification.RejectInvite.PlayerMessage", player.UserIDString), tag));
            if (configData.Options.LogChanges) Instance.LogToFile(Instance.Title, $"{player.displayName} rejected their invite to [{tag}]", Instance);
            return true;
        }
        internal bool JoinClan(BasePlayer player, string tag) {
            if (!player || string.IsNullOrEmpty(tag)) return false;
            if (configData.Permissions.UsePermissionJoin && !permission.UserHasPermission(player.UserIDString, configData.Permissions.PermissionJoin)) {
                player.ChatMessage(msg("Notification.Join.NoPermission", player.UserIDString));
                return false;
            }
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan != null) {
                player.ChatMessage(msg("Notification.Join.InExistingClan", player.UserIDString));
                return false;
            }
            clan = storedData.FindClan(tag);
            if (clan == null) return false;
            return clan.JoinClan(player);
        }
        internal bool LeaveClan(BasePlayer player) {
            if (!player) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            if (configData.Permissions.UsePermissionLeave && !permission.UserHasPermission(player.UserIDString, configData.Permissions.PermissionLeave)) {
                player.ChatMessage(msg("Notification.Leave.NoPermission", player.UserIDString));
                return false;
            }
            return clan.LeaveClan(player);
        }
        internal bool KickPlayer(BasePlayer player, ulong playerId) {
            if (!player) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            if (configData.Permissions.UsePermissionKick && !permission.UserHasPermission(player.UserIDString, configData.Permissions.PermissionKick)) {
                player.ChatMessage(msg("Notification.Kick.NoPermission", player.UserIDString));
                return false;
            }
            return clan.KickMember(player, playerId);
        }
        internal bool PromotePlayer(BasePlayer promoter, ulong targetId) {
            if (!promoter) return false;
            Clan clan = storedData.FindClanByID(promoter.userID);
            if (clan == null) {
                promoter.ChatMessage(msg("Notification.Generic.NoClan", promoter.UserIDString));
                return false;
            }
            Clan other = storedData.FindClanByID(targetId);
            if (other == null || !clan.Tag.Equals(other.Tag)) {
                string displayName = covalence.Players.FindPlayer(targetId.ToString())?.Name ?? targetId.ToString();
                promoter.ChatMessage(string.Format(msg("Notification.Promotion.TargetNoClan", promoter.UserIDString), displayName));
                return false;
            }
            return clan.PromotePlayer(promoter, targetId);
        }
        internal bool DemotePlayer(BasePlayer demoter, ulong targetId) {
            if (!demoter) return false;
            Clan clan = storedData.FindClanByID(demoter.userID);
            if (clan == null) {
                demoter.ChatMessage(msg("Notification.Generic.NoClan", demoter.UserIDString));
                return false;
            }
            Clan other = storedData.FindClanByID(targetId);
            if (other == null || !clan.Tag.Equals(other.Tag)) {
                string displayName = covalence.Players.FindPlayer(targetId.ToString())?.Name ?? targetId.ToString();
                demoter.ChatMessage(string.Format(msg("Notification.Promotion.TargetNoClan", demoter.UserIDString), displayName));
                return false;
            }
            return clan.DemotePlayer(demoter, targetId);
        }
        internal bool DisbandClan(BasePlayer player) {
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            if (!clan.IsOwner(player.userID)) {
                player.ChatMessage(msg("Notification.Disband.NotOwner", player.UserIDString));
                return false;
            }
            if (configData.Permissions.UsePermissionDisband && !permission.UserHasPermission(player.UserIDString, configData.Permissions.PermissionDisband)) {
                player.ChatMessage(msg("Notification.Disband.NoPermission", player.UserIDString));
                return false;
            }
            string tag = clan.Tag;
            clan.LocalizedBroadcast("Notification.Disband.Message", Array.Empty<object>());
            clan.DisbandClan();
            player.ChatMessage(string.Format(msg("Notification.Disband.Success", player.UserIDString), tag));
            return true;
        }
#endregion
#region Alliance Management
        internal bool OfferAlliance(BasePlayer player, string tag) {
            if (!configData.Clans.Alliance.Enabled) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            Clan alliedClan = storedData.FindClan(tag);
            if (alliedClan == null) {
                player.ChatMessage(string.Format(msg("Notification.Generic.InvalidClan", player.UserIDString), tag));
                return false;
            }
            // Update tag from found clan for case insensitive selection
            tag = alliedClan.Tag;
            if (!clan.IsOwner(player.userID) && !clan.IsCouncil(player.userID)) {
                player.ChatMessage(msg("Notification.Alliance.NoPermissions", player.UserIDString));
                return false;
            }
            if (clan.AllianceInvites.ContainsKey(tag) && (UnixTimeStampUTC() - clan.AllianceInvites[tag] < configData.Clans.Invites.AllianceInviteExpireTime)) {
                player.ChatMessage(string.Format(msg("Notification.Alliance.PendingInvite", player.UserIDString), tag));
                return false;
            }
            if (clan.AllianceInviteCount >= configData.Clans.Invites.AllianceInviteLimit) {
                player.ChatMessage(msg("Notification.Alliance.MaximumInvites", player.UserIDString));
                return false;
            }
            if (clan.AllianceCount >= configData.Clans.Alliance.AllianceLimit) {
                player.ChatMessage(msg("Notification.Alliance.MaximumAlliances", player.UserIDString));
                return false;
            }
            if (configData.Clans.Alliance.CountAllianceMembers) {
                int count = clan.CountMembersAndAlliances();
                if (count + alliedClan.MemberCount >= configData.Clans.MemberLimit) {
                    player.ChatMessage(msg("Notification.Alliance.AtLimitAlliedMembersSelf", player.UserIDString));
                    return false;
                }
                count = alliedClan.CountMembersAndAlliances();
                if (count + clan.MemberCount >= configData.Clans.MemberLimit) {
                    player.ChatMessage(string.Format(msg("Notification.Alliance.AtLimitAlliedMembersTarget", player.UserIDString), alliedClan.Tag));
                    return false;
                }
            }
            clan.AllianceInvites[tag] = UnixTimeStampUTC();
            alliedClan.IncomingAlliances.Add(clan.Tag);
            player.ChatMessage(string.Format(msg("Notification.Alliance.InviteSent", player.UserIDString), tag, FormatTime(configData.Clans.Invites.AllianceInviteExpireTime)));
            alliedClan.LocalizedBroadcast("Notification.Alliance.InviteReceived", clan.Tag, FormatTime(configData.Clans.Invites.AllianceInviteExpireTime), configData.Commands.ClanAllyCommand);
            Instance.DiscordClans?.CallHook("LogMessage", $"{player.displayName} has offered an alliance to [{tag}]", (int)MessageType.AllianceInvite);
            return true;
        }
        internal bool WithdrawAlliance(BasePlayer player, string tag) {
            if (!configData.Clans.Alliance.Enabled) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            Clan alliedClan = storedData.FindClan(tag);
            if (alliedClan == null) {
                player.ChatMessage(string.Format(msg("Notification.Generic.InvalidClan", player.UserIDString), tag));
                return false;
            }
            // Update tag from found clan for case insensitive selection
            tag = alliedClan.Tag;
            if (!clan.IsOwner(player.userID) && !clan.IsCouncil(player.userID)) {
                player.ChatMessage(msg("Notification.Alliance.NoPermissions", player.UserIDString));
                return false;
            }
            if (!clan.AllianceInvites.ContainsKey(tag)) {
                player.ChatMessage(string.Format(msg("Notification.Alliance.NoActiveInvite", player.UserIDString), tag));
                return false;
            }
            clan.AllianceInvites.Remove(tag);
            alliedClan.IncomingAlliances.Remove(clan.Tag);
            clan.LocalizedBroadcast("Notification.Alliance.WithdrawnClan", player.displayName, tag);
            alliedClan.LocalizedBroadcast("Notification.Alliance.WithdrawnTarget", clan.Tag);
            clan.MarkDirty();
            Instance.DiscordClans?.CallHook("LogMessage", $"{player.displayName} has withdrawn their alliance offer to [{tag}]", (int)MessageType.AllianceInviteWithdrawn);
            return true;
        }
        internal bool AcceptAlliance(BasePlayer player, string tag) {
            if (!configData.Clans.Alliance.Enabled) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            Clan alliedClan = storedData.FindClan(tag);
            if (alliedClan == null) {
                player.ChatMessage(string.Format(msg("Notification.Generic.InvalidClan", player.UserIDString), tag));
                return false;
            }
            // Update tag from found clan for case insensitive selection
            tag = alliedClan.Tag;
            if (!clan.IsOwner(player.userID) && !clan.IsCouncil(player.userID)) {
                player.ChatMessage(msg("Notification.Alliance.NoPermissions", player.UserIDString));
                return false;
            }
            bool noActiveInvite = !alliedClan.AllianceInvites.ContainsKey(clan.Tag);
            if ((UnixTimeStampUTC() - alliedClan.AllianceInvites[clan.Tag] > configData.Clans.Invites.AllianceInviteExpireTime)) {
                alliedClan.AllianceInvites.Remove(clan.Tag);
                noActiveInvite = true;
            }
            if (noActiveInvite) {
                player.ChatMessage(string.Format(msg("Notification.Alliance.NoActiveInviteFrom", player.UserIDString), tag));
                return false;
            }
            if (alliedClan.AllianceCount >= configData.Clans.Alliance.AllianceLimit) {
                player.ChatMessage(string.Format(msg("Notification.Alliance.AtLimitTarget", player.UserIDString), tag));
                return false;
            }
            if (clan.AllianceCount >= configData.Clans.Alliance.AllianceLimit) {
                player.ChatMessage(string.Format(msg("Notification.Alliance.AtLimitSelf", player.UserIDString), tag));
                return false;
            }
            if (configData.Clans.Alliance.CountAllianceMembers) {
                int count = clan.CountMembersAndAlliances();
                if (count + alliedClan.MemberCount >= configData.Clans.MemberLimit) {
                    player.ChatMessage(msg("Notification.Alliance.AtLimitAlliedMembersSelf", player.UserIDString));
                    return false;
                }
                count = alliedClan.CountMembersAndAlliances();
                if (count + clan.MemberCount >= configData.Clans.MemberLimit) {
                    player.ChatMessage(string.Format(msg("Notification.Alliance.AtLimitAlliedMembersTarget", player.UserIDString), alliedClan.Tag));
                    return false;
                }
            }
            clan.Alliances.Add(tag);
            clan.IncomingAlliances.Remove(tag);
            alliedClan.Alliances.Add(clan.Tag);
            alliedClan.AllianceInvites.Remove(clan.Tag);
            clan.MarkDirty();
            alliedClan.MarkDirty();
            clan.LocalizedBroadcast("Notification.Alliance.Formed", clan.Tag, alliedClan.Tag);
            alliedClan.LocalizedBroadcast("Notification.Alliance.Formed", clan.Tag, alliedClan.Tag);
            Interface.Oxide.CallHook("OnClanUpdate", clan.Tag);
            Interface.Oxide.CallHook("OnClanUpdate", alliedClan.Tag);
            Instance.DiscordClans?.CallHook("LogMessage", $"{player.displayName} has accepted a alliance offer from [{tag}]", (int)MessageType.AllianceAccept);
            return true;
        }
        internal bool RejectAlliance(BasePlayer player, string tag) {
            if (!configData.Clans.Alliance.Enabled) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            Clan alliedClan = storedData.FindClan(tag);
            if (alliedClan == null) {
                player.ChatMessage(string.Format(msg("Notification.Generic.InvalidClan", player.UserIDString), tag));
                return false;
            }
            // Update tag from found clan for case insensitive selection
            tag = alliedClan.Tag;
            if (!clan.IsOwner(player.userID) && !clan.IsCouncil(player.userID)) {
                player.ChatMessage(msg("Notification.Alliance.NoPermissions", player.UserIDString));
                return false;
            }
            if (!alliedClan.AllianceInvites.ContainsKey(clan.Tag) || (UnixTimeStampUTC() - alliedClan.AllianceInvites[clan.Tag] > configData.Clans.Invites.AllianceInviteExpireTime)) {
                player.ChatMessage(string.Format(msg("Notification.Alliance.NoActiveInvite", player.UserIDString), tag));
                return false;
            }
            clan.IncomingAlliances.Remove(tag);
            alliedClan.AllianceInvites.Remove(clan.Tag);
            alliedClan.MarkDirty();
            clan.LocalizedBroadcast("Notification.Alliance.Rejected", clan.Tag, alliedClan.Tag);
            alliedClan.LocalizedBroadcast("Notification.Alliance.Rejected", clan.Tag, alliedClan.Tag);
            Instance.DiscordClans?.CallHook("LogMessage", $"{player.displayName} has rejected a alliance offer from [{tag}]", (int)MessageType.AllianceInviteReject);
            return true;
        }
        internal bool RevokeAlliance(BasePlayer player, string tag) {
            if (!configData.Clans.Alliance.Enabled) return false;
            Clan clan = storedData.FindClanByID(player.userID);
            if (clan == null) {
                player.ChatMessage(msg("Notification.Generic.NoClan", player.UserIDString));
                return false;
            }
            Clan alliedClan = storedData.FindClan(tag);
            if (alliedClan == null) {
                player.ChatMessage(string.Format(msg("Notification.Generic.InvalidClan", player.UserIDString), tag));
                return false;
            }
            // Update tag from found clan for case insensitive selection
            tag = alliedClan.Tag;
            if (!clan.IsOwner(player.userID) && !clan.IsCouncil(player.userID)) {
                player.ChatMessage(msg("Notification.Alliance.NoPermissions", player.UserIDString));
                return false;
            }
            if (!clan.Alliances.Contains(alliedClan.Tag)) {
                player.ChatMessage(string.Format(msg("Notification.Alliance.NoActiveAlliance", player.UserIDString), alliedClan.Tag));
                return false;
            }
            alliedClan.Alliances.Remove(clan.Tag);
            clan.Alliances.Remove(alliedClan.Tag);
            alliedClan.MarkDirty();
            clan.MarkDirty();
            clan.LocalizedBroadcast("Notification.Alliance.Revoked", clan.Tag, alliedClan.Tag);
            alliedClan.LocalizedBroadcast("Notification.Alliance.Revoked", clan.Tag, alliedClan.Tag);
            Interface.Oxide.CallHook("OnClanUpdate", clan.Tag);
            Interface.Oxide.CallHook("OnClanUpdate", alliedClan.Tag);
            Instance.DiscordClans?.CallHook("LogMessage", $"{player.displayName} has withdrawn their alliance to [{tag}]", (int)M
// ... [Code preview truncated due to length. Full source in attached file] ...

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