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

FREE IQTeamLimitter : 1.4.5 1.4.5

Нет прав для скачивания
C#:
using ProtoBuf;
using Newtonsoft.Json.Linq;
using UnityEngine;
using Oxide.Core;
using Facepunch;
using System;
using System.Text;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using Object = System.Object;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Oxide.Plugins {
    [Info("IQTeamLimitter", "Mercury", "1.4.5")]
    [Description("Monitoring and logging the actions of players with teams")]
    class IQTeamLimitter : RustPlugin {
        private void OnServerInitialized() {
            RelationshipManager manager = RelationshipManager.ServerInstance;
            Int32 countTeams = manager ? manager.teams.Count : 0;
            Puts(LanguageEn ? $"There are {countTeams} teams of players on the server" : $"На сервере существует {countTeams} команд из игроков");
            foreach (BasePlayer player in BasePlayer.activePlayerList) OnPlayerConnected(player);
        }
        private void OnServerShutdown() => Unload();
        private void OnTeamLeave(RelationshipManager.PlayerTeam team, BasePlayer player) {
            if (team.members.Count == 1) {
                String logMessageLeaveCountNull = LanguageEn ? $"{player.displayName}({player.UserIDString}) has disbanded their team and left it." : $"{player.displayName}({player.UserIDString}) удалил свою команду и покинул ее";
                LoggedProcess(ref logMessageLeaveCountNull);
                return;
            }
            PlayerInfo pData = PlayerInfo.Get(player.UserIDString);
            if (pData == null) return;
            if (pData.IsLimit()) return;
            pData.cooldownAddedTeams = config.GetCooldown();
            SendChat(GetLang("ALERT_LEAVE_TEAM", player.UserIDString, FormatTime(pData.GetCooldown()), pData.GetLimit()), player);
            String logMessageLeave = LanguageEn ? $"{player.displayName}({player.UserIDString}) has left the team." : $"{player.displayName}({player.UserIDString}) покинул команду";
            LoggedProcess(ref logMessageLeave);
        }
        private void Init() {
            ReadData();
            LoadDataFiles();
        }
        private Object OnTeamCreate(BasePlayer player) {
            PlayerInfo pData = PlayerInfo.Get(player.UserIDString);
            if (pData == null) return null;
            if (pData.IsLimit()) {
                SendChat(GetLang("INFO_ALERT_CREATE_TEAM", player.UserIDString), player);
                return false;
            }
            String messageKey = pData.IsCooldown() ? "INFO_ALERT_PLUS_COOLDOWN" : "INFO_ALERT";
            SendChat(GetLang(messageKey, player.UserIDString, pData.GetLimit(), FormatTime(pData.GetCooldown())), player);
            String logMessageCreate = LanguageEn ? $"{player.displayName}({player.UserIDString}) has created a team." : $"{player.displayName}({player.UserIDString}) создал команду";
            LoggedProcess(ref logMessageCreate);
            return null;
        }
        private readonly Dictionary<BasePlayer, Int32> inviteCooldownLog = new Dictionary<BasePlayer, Int32>();
        private class PlayerInfo : SplitDatafile<PlayerInfo> {
            private const String BaseFolder = "IQSystem" + "/" + "IQTeamLimitter" + "/" + "Players" + "/";
            public static PlayerInfo Save(String id) => Save(BaseFolder, id);
            public static void Import(String id, PlayerInfo data) => Import(BaseFolder, id, data);
            public static void Remove(String id) => Remove(BaseFolder, id);
            public static PlayerInfo Get(String id) => Get(BaseFolder, id);
            public static PlayerInfo Load(String id) => Load(BaseFolder, id);
            public static PlayerInfo Clear(String id) => ClearAndSave(BaseFolder, id);
            public static PlayerInfo GetOrLoad(String id) => GetOrLoad(BaseFolder, id);
            public static PlayerInfo GetOrCreate(String id) => GetOrCreate(BaseFolder, id);
            public static String[] GetFiles() => GetFiles(BaseFolder);
            public Int32 cooldownAddedTeams;
            public Int32 addTeamCount;
            public Boolean IsLimit() => addTeamCount >= config.limitTeam;
            public Boolean IsCooldown() => GetCooldown() > 0;
            public Int32 GetCooldown() => cooldownAddedTeams - CurrentTime;
            public Double GetLimit() => (config.limitTeam - addTeamCount) <= 0 ? 0 : config.limitTeam - addTeamCount;
        }
        public Dictionary<UInt64, String> kickAlert = new Dictionary<UInt64, String>();
        private static Configuration config = new Configuration();
        private void OnNewSave(String filename) => DetectedWipe();
        protected override void SaveConfig() => Config.WriteObject(config);
        public class Configuration {
            [JsonProperty(LanguageEn ? "Disband all teams after the wipe (true - yes/false - no)" : "Расформировать все команды после вайпа (true - да/false - нет)")]
            public Boolean clearAllTeamAfterWipe;
            [JsonProperty(LanguageEn ? "Configuration of supported plugins" : "Настройка поддерживаемых плагинов")]
            public ReferencePlugins referencePlugins = new ReferencePlugins();
            internal class LogController {
                internal class LogToDiscord {
                    [JsonProperty(LanguageEn ? "Webhooks: Log all actions with teams to the Discord channel" : "Webhooks: Логирование всех действий с командами в канал Discord")]
                    public String webhooksDiscord;
                    [JsonProperty(LanguageEn ? "Webhooks: Avatar for the webhook (direct link)" : "Webhooks: Аватар для вебхука (прямая ссылка)")]
                    public String avatartDiscord;
                    [JsonProperty(LanguageEn ? "Webhooks: Name for the webhook" : "Webhooks: Название для вебхука")]
                    public String nameDiscord;
                }
                [JsonProperty(LanguageEn ? "Log data to file" : "Логирование данных в файл")]
                public Boolean logToFile;
                [JsonProperty(LanguageEn ? "Log data to Discord" : "Логирование данных в Discord")]
                public LogToDiscord discordLogSetting = new LogToDiscord();
            }
            public class ReferencePlugins {
                [JsonProperty(LanguageEn ? "IQChat: Chat notification settings" : "IQChat: Настройка уведомлений в чате")]
                public IQChatPreset iqchatPreset = new IQChatPreset();
                public class IQChatPreset {
                    [JsonProperty(LanguageEn ? "IQChat: Custom prefix in chat" : "IQChat: Кастомный префикс в чате")]
                    public String customPrefix;
                    [JsonProperty(LanguageEn ? "IQChat: Custom avatar in chat (if required)" : "IQChat: Кастомный аватар в чате (если требуется)")]
                    public String customAvatar;
                }
            }
            [JsonProperty(LanguageEn ? "Limit on adding to the team during the wipe (if the limit is exhausted, the player will not be able to join teams)" : "Лимит на добавление в команду в течение вайпа (если лимит исчерпан, игрок не сможет вступать в команды)")]
            public Int32 limitTeam;
            public Int32 GetCooldown() => CurrentTime + (cooldownMinutes * 60);
            [JsonProperty(LanguageEn ? "Cooldown time for joining a new team or inviting players after being removed from a team or leaving it (in minutes)" : "Время перезарядки для вступления в новую команду или приглашения игроков после удаления из команды или выхода из неё (в минутах)")]
            public Int32 cooldownMinutes;
            public static Configuration GetNewConfiguration() {
                return new Configuration {
                    limitTeam = 3, cooldownMinutes = 60, clearAllTeamAfterWipe = true, logController = new LogController {
                        logToFile = false, discordLogSetting = new LogController.LogToDiscord {
                            webhooksDiscord = String.Empty, nameDiscord = "[IQTeamLimitter]", avatartDiscord = ""
                        }
                    }
                    , referencePlugins = new ReferencePlugins() {
                        iqchatPreset = new ReferencePlugins.IQChatPreset() {
                            customAvatar = "0", customPrefix = "<color=#1F6BA0>[IQTeamLimitter]\n</color>",
                        }
                    }
                }
                ;
            }
            [JsonProperty(LanguageEn ? "Logging settings for team actions" : "Настройки логирования действий с командами")]
            public LogController logController = new LogController();
        }
        private abstract class SplitDatafile<T> where T : SplitDatafile<T>, new() {
            public static Dictionary<String, T> _players = new();
            protected static void Import(String baseFolder, String userId, T data) {
                _players[userId] = data;
                Save(baseFolder, userId);
            }
            protected static String[] GetFiles(String baseFolder) {
                try {
                    Int32 json = ".json".Length;
                    String[] paths = Interface.Oxide.DataFileSystem.GetFiles(baseFolder, "*.json");
                    for (Int32 i = 0; i < paths.Length; i++) {
                        String path = paths[i];
                        Int32 separatorIndex = path.LastIndexOf("/", StringComparison.Ordinal);
                        paths[i] = path.Substring(separatorIndex + 1, path.Length - separatorIndex - 1 - json);
                    }
                    return paths;
                }
                catch {
                    return Array.Empty<string>();
                }
            }
            protected static T Save(string baseFolder, String userId) {
                T data;
                if (!_players.TryGetValue(userId, out data)) return null;
                Interface.Oxide.DataFileSystem.WriteObject(baseFolder + userId, data);
                return data;
            }
            protected static void Remove(string baseFolder, String userId) {
                if (!_players.ContainsKey(userId)) return;
                _players.Remove(userId);
                Interface.Oxide.DataFileSystem.DeleteDataFile(baseFolder + userId);
            }
            protected static T Get(string baseFolder, String userId) {
                T data;
                if (_players.TryGetValue(userId, out data)) return data;
                return null;
            }
            protected static T Load(String baseFolder, String userId) {
                T data = null;
                try {
                    data = Interface.Oxide.DataFileSystem.ReadObject<T>(baseFolder + userId);
                }
                catch (Exception e) {
                    Interface.Oxide.LogError(e.ToString());
                }
                return _players[userId] = data;
            }
            protected static T GetOrLoad(String baseFolder, String userId) {
                T data;
                if (_players.TryGetValue(userId, out data)) return data;
                return Load(baseFolder, userId);
            }
            protected static T GetOrCreate(String baseFolder, String userId) {
                return GetOrLoad(baseFolder, userId) ?? (_players[userId] = new T());
            }
            protected static T ClearAndSave(String baseFolder, String userId) {
                T data;
                if (_players.TryGetValue(userId, out data)) {
                    data = new T();
                    Interface.Oxide.DataFileSystem.WriteObject(baseFolder + userId, data);
                    return data;
                }
                return null;
            }
        }
        private static Int32 CurrentTime => Facepunch.Math.Epoch.Current;
        protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
        [ConsoleCommand("tc")]
        private void TCConsoleCMD(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if(player != null) if (!player.IsAdmin) return;
            if (!arg.HasArgs(1)) {
                Puts(LanguageEn ? "Use the correct syntax : tc Steam64ID" : "Используйте корректный синтаксис : tc Steam64ID");
                return;
            }
            String userID = arg.Args[0];
            if (!userID.IsSteamId()) {
                Puts(LanguageEn ? "The Steam64ID is specified incorrectly" : "Неверно указан Steam64ID");
                return;
            }
            PlayerInfo pData = PlayerInfo.Get(userID);
            if (pData == null) {
                Puts(LanguageEn ? "Such a player does not exist in the database" : "Такой игрок не существует в базе данных");
                return;
            }
            pData.cooldownAddedTeams = 0;
            Puts(LanguageEn ? $"You have successfully reset the friend request cooldown for player {userID}" : $"Вы успешно сбросили перезарядку на добавления в друзья для игрока {userID}");
        }
        private void WriteData() => Oxide.Core.Interface.Oxide.DataFileSystem.WriteObject("IQSystem/IQTeamLimitter/AlertPlayersAfterKick", kickAlert);
        private Boolean IsCooldownLog(BasePlayer target) {
            if (!target) return false;
            if (inviteCooldownLog.TryGetValue(target, out Int32 cooldownLog)) {
                if (cooldownLog > CurrentTime) return true;
            }
            inviteCooldownLog[target] = CurrentTime + 60;
            return false;
        }
        [PluginReference]
        Plugin IQChat;
        private readonly Dictionary<BasePlayer, BasePlayer> activeInvite = new Dictionary<BasePlayer, BasePlayer>();
        [ConsoleCommand("tl")]
        private void TLConsoleCMD(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if(player != null) if (!player.IsAdmin) return;
            if (!arg.HasArgs(2)) {
                Puts(LanguageEn ? "Use the correct syntax : tl Steam64ID Number" : "Используйте корректный синтаксис : tl Steam64ID Количество");
                return;
            }
            String userID = arg.Args[0];
            if (!userID.IsSteamId()) {
                Puts(LanguageEn ? "The Steam64ID is specified incorrectly" : "Неверно указан Steam64ID");
                return;
            }
            PlayerInfo pData = PlayerInfo.Get(userID);
            if (pData == null) {
                Puts(LanguageEn ? "Such a player does not exist in the database" : "Такой игрок не существует в базе данных");
                return;
            }
            if (!Int32.TryParse(arg.Args[1], out Int32 count)) {
                Puts(LanguageEn ? "You must specify the value in numbers" : "Вы должны указать значение в цифрах");
                return;
            }
            pData.addTeamCount -= count;
            if (pData.addTeamCount < 0) pData.addTeamCount = 0;
            Puts(LanguageEn ? $"You have successfully reset the player's limit on {count} values. The current player limit is: {pData.addTeamCount}/{config.limitTeam}" : $"Вы успешно сбросили лимит игрока на {count} значения. Текущий лимит игрока : {pData.addTeamCount}/{config.limitTeam}");
        }
        private void LoadDataFiles() {
            String[] players = PlayerInfo.GetFiles();
            foreach (String player in players) PlayerInfo.Load(player);
            Puts(LanguageEn ? $"The {players.Length} database of players has been initialized" : $"Инициализирована база данных {players.Length} игроков");
        }
        private void OnTeamRejectInvite(BasePlayer rejector, RelationshipManager.PlayerTeam team) {
            if (!activeInvite.TryGetValue(rejector, out BasePlayer inviter)) return;
            String logMessageAccepted = inviter == null ? (LanguageEn ? $"{rejector.displayName}({rejector.UserIDString}) decided not to accept the team invitation." : $"{rejector.displayName}({rejector.UserIDString}) отклонил приглашение в команду") : (LanguageEn ? $"{rejector.displayName}({rejector.UserIDString}) has declined the team invitation from {inviter.displayName}({inviter.UserIDString})." : $"{rejector.displayName}({rejector.UserIDString}) отклонил приглашение в команду от {inviter.displayName}({inviter.UserIDString})");
            LoggedProcess(ref logMessageAccepted);
            activeInvite.Remove(rejector);
        }
        private void OnPlayerConnected(BasePlayer player) {
            PlayerInfo playerInfo = PlayerInfo.Get(player.UserIDString);
            if (playerInfo == null) {
                playerInfo = new PlayerInfo {
                    cooldownAddedTeams = 0, addTeamCount = 0,
                }
                ;
                PlayerInfo.Import(player.UserIDString, playerInfo);
            }
            if (kickAlert == null || !kickAlert.ContainsKey(player.userID)) return;
            String messageKey = playerInfo.IsCooldown() ? "ALERT_ACCEPT_KICK_PLAYER_COOLDOWN" : "ALERT_ACCEPT_KICK_PLAYER";
            SendChat(GetLang(messageKey, player.UserIDString, kickAlert[player.userID], playerInfo.GetLimit(), FormatTime(playerInfo.GetCooldown())), player);
            kickAlert.Remove(player.userID);
        }
        private void SendChat(String Message, BasePlayer player, ConVar.Chat.ChatChannel channel = ConVar.Chat.ChatChannel.Global) {
            if (IQChat) IQChat?.Call("API_ALERT_PLAYER", player, Message, config.referencePlugins.iqchatPreset.customPrefix, config.referencePlugins.iqchatPreset.customAvatar);
            else player.SendConsoleCommand("chat.add", channel, 0, Message);
        }
        private void OnTeamAcceptInvite(RelationshipManager.PlayerTeam team, BasePlayer target) {
            if (!activeInvite.TryGetValue(target, out BasePlayer inviter)) return;
            PlayerInfo iData = PlayerInfo.Get(inviter.UserIDString);
            if (iData == null) return;
            PlayerInfo tData = PlayerInfo.Get(target.UserIDString);
            if (tData == null) return;
            Int32 cooldown = config.GetCooldown();
            iData.cooldownAddedTeams = cooldown;
            tData.cooldownAddedTeams = 0;
            iData.addTeamCount++;
            tData.addTeamCount++;
            activeInvite.Remove(target);
            SendChat(GetLang("ALERT_ACCEPT_TEAM", target.UserIDString, tData.GetLimit()), target);
            SendChat(GetLang("ALERT_ACCEPT_TEAM_INVITER", inviter.UserIDString, iData.GetLimit()), inviter);
            String logMessageAccepted = LanguageEn ? $"{target.displayName}({target.UserIDString}) has accepted the team invitation from {inviter.displayName}({inviter.UserIDString})." : $"{target.displayName}({target.UserIDString}) принял приглашение в команду от {inviter.displayName}({inviter.UserIDString})";
            LoggedProcess(ref logMessageAccepted);
        }
        public static String FormatTime(in Single source) {
            StringBuilder stringBuilder = Pool.Get<StringBuilder>();
            TimeSpan ts = TimeSpan.FromSeconds(source);
            try {
                String str;
                if (ts.TotalHours >= 24) {
                    str = stringBuilder.AppendFormat("{0:D2}:{1:D2}:{2:D2}", (Int32)ts.TotalHours, ts.Minutes, ts.Seconds).ToString();
                }
                else if (ts.Hours > 0) {
                    str = stringBuilder.AppendFormat("{0:D2}:{1:D2}:{2:D2}", ts.Hours, ts.Minutes, ts.Seconds).ToString();
                }
                else {
                    str = stringBuilder.AppendFormat("{0:D2}:{1:D2}", ts.Minutes, ts.Seconds).ToString();
                }
                return str;
            }
            finally {
                stringBuilder.Clear();
                Pool.FreeUnmanaged(ref stringBuilder);
            }
        }
        private void ReadData() => kickAlert = Oxide.Core.Interface.Oxide.DataFileSystem.ReadObject<Dictionary<UInt64, String>>("IQSystem/IQTeamLimitter/AlertPlayersAfterKick");
        private void Request(String url, String payload, Action<Int32> callback = null) {
            Dictionary<String, String> header = new Dictionary<String, String>();
            header.Add("Content-Type", "application/json");
            webrequest.Enqueue(url, payload, (code, response) => {
                if (code != 200 && code != 204) {
                    if (response != null) {
                        try {
                            JObject json = JObject.Parse(response);
                            if (code != 429 || response.Contains("key:73888965")) PrintWarning($"Discord rejected that payload! Responded with \"{json["message"].ToString()}\" Code: {code}");
                        }
                        catch {
                            PrintWarning($"Failed to get a valid response from discord! Error: \"{response}\" Code: {code}");
                        }
                    }
                    else {
                        PrintWarning($"Discord didn't respond (down?) Code: {code}");
                    }
                }
                try {
                    callback?.Invoke(code);
                }
                catch (Exception ex) {
                }
            }
            , this, RequestMethod.POST, header);
        }
        private new void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<String, String> {
                ["INFO_ALERT"]
                = "Limit on joining and inviting to the team: <color=#738D45>{0}</color>", ["INFO_ALERT_PLUS_COOLDOWN"] = "Limit on joining and inviting to the team: <color=#738D45>{0}</color>\nCooldown before the next joining: <color=#CD412B>{1}</color>", ["INFO_ALERT_CREATE_TEAM"] = "Вы исчерпали командный лимит, вам запрещено создавать команды!", ["ALERT_ACCEPT_KICK_PLAYER_COOLDOWN"] = "<color=#1F6BA0>{0}</color> kicked you from the team.\n\nRemaining available joining limits: <color=#738D45>{1}</color>\nCooldown before the next joining: <color=#CD412B>{2}</color>", ["ALERT_ACCEPT_KICK_PLAYER"] = "<color=#1F6BA0>{0}</color> kicked you from the team.\n\nRemaining available joining limits: <color=#738D45>{1}</color>", ["ALERT_ACCEPT_KICK_LEADER"] = "You have successfully removed a player from the team.\n\nRemaining available invitation limits: <color=#738D45>{0}</color>\nCooldown before the next invitation: <color=#CD412B>{1}</color>", ["ALERT_ACCEPT_TEAM_INVITER"] = "The player has successfully joined your team.\n\nRemaining available invitation limits: <color=#738D45>{0}</color>\n\nNote: if you remove the player or leave the team, you will receive a temporary invitation ban and lose one limit point.", ["ALERT_ACCEPT_TEAM"] = "You have successfully joined the team.\n\nRemaining available joining limits for another team: <color=#738D45>{0}</color>\n\nNote: if you leave the team or are removed, you will receive a temporary joining ban and lose one limit point.", ["ALERT_LEAVE_TEAM"] = "You have left the team. You will be able to join a new one in <color=#CD412B>{0}</color>.\n\nRemaining available joining limits for another team: <color=#738D45>{1}</color>", ["ALERT_COOLDOWN_TARGET_TEAM_INVITE"] = "Cannot invite player to the team: they cannot accept invitations for another <color=#CD412B>{0}</color>.", ["ALERT_COOLDOWN_TEAM_INVITE"] = "You cannot invite players to the team.\n\nPlease wait another <color=#CD412B>{0}</color>.", ["ALERT_LIMITED_TEAM"] = "Your limit for joining teams is exhausted.\n\n<color=#CD412B>You are prohibited from joining and inviting players until the next wipe.</color>", ["ALERT_LIMITED_TEAM_PLAYER"] = "<color=#1F6BA0>{0}</color> has exhausted their limit for joining teams.\n\n<color=#CD412B>They are prohibited from joining and inviting players until the next wipe.</color>",
            }
            , this);
            lang.RegisterMessages(new Dictionary<String, String> {
                ["INFO_ALERT"]
                = "Лимит на вступления и приглашения в команду: <color=#738D45>{0}</color>", ["INFO_ALERT_CREATE_TEAM"] = "Вы исчерпали командный лимит, вам запрещено создавать команды!", ["INFO_ALERT_PLUS_COOLDOWN"] = "Лимит на вступления и приглашения в команду: <color=#738D45>{0}</color>\nВремя ожидания до следующего вступления: <color=#CD412B>{1}</color>", ["ALERT_ACCEPT_KICK_PLAYER_COOLDOWN"] = "<color=#1F6BA0>{0}</color> исключил вас из команды.\n\nОсталось доступных лимитов для вступления: <color=#738D45>{1}</color>\nВремя ожидания до следующего вступления: <color=#CD412B>{2}</color>", ["ALERT_ACCEPT_KICK_PLAYER"] = "<color=#1F6BA0>{0}</color> исключил вас из команды.\n\nОсталось доступных лимитов для вступления: <color=#738D45>{1}</color>", ["ALERT_ACCEPT_KICK_LEADER"] = "Вы успешно исключили игрока из команды.\n\nОсталось доступных лимитов для приглашения: <color=#738D45>{0}</color>\nВремя ожидания до следующего приглашения: <color=#CD412B>{1}</color>", ["ALERT_ACCEPT_TEAM_INVITER"] = "Игрок успешно присоединился к вашей команде.\n\nОсталось доступных лимитов для приглашения: <color=#738D45>{0}</color>\n\nВажно: если вы удалите игрока или покинете команду, вы получите временную блокировку на приглашения и потеряете единицу лимита.", ["ALERT_ACCEPT_TEAM"] = "Вы успешно вступили в команду.\n\nОсталось доступных лимитов для вступления в другую команду: <color=#738D45>{0}</color>\n\nВажно: если вы покинете команду или вас исключат, вы получите временную блокировку на вступление и потеряете единицу лимита.", ["ALERT_LEAVE_TEAM"] = "Вы покинули команду. Вы сможете вступить в новую через <color=#CD412B>{0}</color>.\n\nОсталось доступных лимитов для вступления в другую команду: <color=#738D45>{1}</color>", ["ALERT_COOLDOWN_TARGET_TEAM_INVITE"] = "Невозможно пригласить игрока в команду: он не может принимать заявки ещё <color=#CD412B>{0}</color>.", ["ALERT_COOLDOWN_TEAM_INVITE"] = "Вы не можете приглашать игроков в команду.\n\nПожалуйста, подождите ещё <color=#CD412B>{0}</color>.", ["ALERT_LIMITED_TEAM"] = "Ваш лимит на объединение в команды исчерпан.\n\n<color=#CD412B>Вам запрещено присоединяться и приглашать игроков до следующего вайпа.</color>", ["ALERT_LIMITED_TEAM_PLAYER"] = "<color=#1F6BA0>{0}</color> исчерпал свой лимит на объединение в команды.\n\n<color=#CD412B>Ему запрещено присоединяться и приглашать игроков до следующего вайпа.</color>",
            }
            , this, "ru");
        }
        private class BotMessage {
            [JsonProperty("content")]
            public String Content {
                get;
                set;
            }
            [JsonProperty("username")]
            public String Username {
                get;
                set;
            }
            [JsonProperty("avatar_url")]
            public String AvatarUrl {
                get;
                set;
            }
        }
        private void LoggedProcess(ref String message) {
            message = $"{DateTime.UtcNow:[dd.MM.yyyy-HH:mm]} {message}";
            LogToFile(message);
            SendDiscord(message);
        }
        private Object OnTeamMemberInvite(PlayerTeam playerTeam, BasePlayer inviter, UInt64 targetId) {
            PlayerInfo iData = PlayerInfo.Get(inviter.UserIDString);
            if (iData == null) return null;
            BasePlayer target = BasePlayer.FindByID(targetId);
            if(target == null) return null;
            PlayerInfo tData = PlayerInfo.Get(target.UserIDString);
            if (tData == null) return null;
            Boolean isCooldownLog = IsCooldownLog(target);
            if (!isCooldownLog) {
                String logMessageTryInvite = LanguageEn ? $"{inviter.displayName}({inviter.UserIDString}) is trying to invite {target.displayName}({target.UserIDString}) to join their team." : $"{inviter.displayName}({inviter.UserIDString}) пытается пригласить в команду {target.displayName}({target.UserIDString})";
                LoggedProcess(ref logMessageTryInvite);
            }
            if (iData.IsLimit()) {
                SendChat(GetLang("ALERT_LIMITED_TEAM", inviter.UserIDString), inviter);
                return false;
            }
            if (tData.IsLimit()) {
                SendChat(GetLang("ALERT_LIMITED_TEAM_PLAYER", inviter.UserIDString, target.displayName), inviter);
                return false;
            }
            if (iData.IsCooldown()) {
                SendChat(GetLang("ALERT_COOLDOWN_TEAM_INVITE", inviter.UserIDString, FormatTime(iData.GetCooldown())), inviter);
                return false;
            }
            if (tData.IsCooldown()) {
                SendChat(GetLang("ALERT_COOLDOWN_TARGET_TEAM_INVITE", inviter.UserIDString, FormatTime(tData.GetCooldown())), inviter);
                return false;
            }
            activeInvite.TryAdd(target, inviter);
            if (!isCooldownLog) {
                String logMessageInvited = LanguageEn ? $"{inviter.displayName}({inviter.UserIDString}) has invited {target.displayName}({target.UserIDString}) to the team." : $"{inviter.displayName}({inviter.UserIDString}) пригласил в команду {target.displayName}({target.UserIDString})";
                LoggedProcess(ref logMessageInvited);
            }
            return null;
        }
        [ChatCommand("info.team")]
        private void InfoTeamChatCommand(BasePlayer player) {
            if (player == null) return;
            PlayerInfo pData = PlayerInfo.Get(player.UserIDString);
            if (pData == null) return;
            String messageKey = pData.IsCooldown() ? "INFO_ALERT_PLUS_COOLDOWN" : "INFO_ALERT";
            String message = GetLang(messageKey, player.UserIDString, pData.GetLimit(), FormatTime(pData.GetCooldown()));
            SendChat(message, player);
            player.ConsoleMessage(message);
        }
        private void LogToFile(in String message) {
            if (!config.logController.logToFile) return;
            LogToFile("TeamLogs", message, this, true, true);
        }
        private void SaveDataFiles() {
            foreach (KeyValuePair<String, PlayerInfo> player in PlayerInfo._players) PlayerInfo.Save(player.Key);
            PlayerInfo._players.Clear();
        }
        private void OnTeamKick(RelationshipManager.PlayerTeam team, BasePlayer player, UInt64 targetID) {
            PlayerInfo pData = PlayerInfo.Get(player.UserIDString);
            if (pData == null) return;
            String targetIDString = targetID.ToString();
            PlayerInfo tData = PlayerInfo.Get(targetIDString);
            if (tData == null) return;
            pData.addTeamCount++;
            pData.cooldownAddedTeams = config.GetCooldown();
            tData.addTeamCount++;
            tData.cooldownAddedTeams = config.GetCooldown();
            BasePlayer target = BasePlayer.FindByID(targetID);
            if (target == null) kickAlert.TryAdd(targetID, player.displayName);
            else SendChat(GetLang("ALERT_ACCEPT_KICK_PLAYER_COOLDOWN", targetIDString, player.displayName, tData.GetLimit(), FormatTime(tData.GetCooldown())), target);
            SendChat(GetLang("ALERT_ACCEPT_KICK_LEADER", player.UserIDString, pData.GetLimit(), FormatTime(pData.GetCooldown())), player);
            String logMessageKick = LanguageEn ? $"{player.displayName}({player.UserIDString}) has kicked {(target != null ? target.displayName : "Unknown")}({targetID}) from the team." : $"{player.displayName}({player.UserIDString}) кикнул из команды {(target != null ? target.displayName : "Unknown")}({targetID})";
            LoggedProcess(ref logMessageKick);
        }
        private String GetLang(in String LangKey, in String userID = null, params Object[] args) {
            if (args == null) return lang.GetMessage(LangKey, this, userID);
            StringBuilder sb = Pool.Get<StringBuilder>();
            try {
                sb.AppendFormat(lang.GetMessage(LangKey, this, userID), args);
                return sb.ToString();
            }
            finally {
                sb.Clear();
                Pool.FreeUnmanaged(ref sb);
            }
        }
        /// <summary>
        /// - Исправлена ошибка в OnPlayerConnected, когда игрок впервые зашел на сервер и его данные некорректно обработались
        /// - Обновлен хук, который устареет после 31 декабря
        /// </summary>
        private const Boolean LanguageEn = false;
        private void DetectedWipe() {
            List<String> playersID = Pool.GetList<String>();
            playersID.AddRange(PlayerInfo._players.Keys);
            foreach (String playerKeys in playersID) PlayerInfo.Remove(playerKeys);
            Pool.FreeList(ref playersID);
            if (!config.clearAllTeamAfterWipe) return;
            RelationshipManager manager = RelationshipManager.ServerInstance;
            Int32 countTeams = manager ? manager.teams.Count : 0;
            Puts(LanguageEn ? $"{countTeams} player teams have been removed." : $"Удалено {countTeams} команд игроков");
            if (manager == null) return;
            manager.cachedPlayers.Clear();
            manager.playerToTeam.Clear();
            manager.relationships.Clear();
            manager.teams.Clear();
            manager.SendNetworkUpdate();
        }
        private void Unload() {
            WriteData();
            SaveDataFiles();
            if (inviteCooldownLog != null && inviteCooldownLog.Count != 0) inviteCooldownLog.Clear();
            if (activeInvite != null && activeInvite.Count != 0) activeInvite.Clear();
        }
        private void SendDiscord(in String message) {
            Configuration.LogController.LogToDiscord discordController = config.logController.discordLogSetting;
            if (discordController.webhooksDiscord == null || String.IsNullOrWhiteSpace(discordController.webhooksDiscord)) return;
            BotMessage newMessage = new BotMessage {
                Content = message, Username = discordController.nameDiscord, AvatarUrl = discordController.avatartDiscord,
            }
            ;
            String jsonPayload = JsonConvert.SerializeObject(newMessage, Formatting.Indented);
            Request(discordController.webhooksDiscord, jsonPayload);
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                config = Config.ReadObject<Configuration>();
                if (config == null) LoadDefaultConfig();
            }
            catch {
                PrintWarning(LanguageEn ? $"Error reading #321562 configuration 'oxide/config/{Name}', creating a new configuration!!" : $"Ошибка чтения #3212 конфигурации 'oxide/config/{Name}', создаём новую конфигурацию!!");
                LoadDefaultConfig();
            }
            NextTick(SaveConfig);
        }
        [ConsoleCommand("tinfo")]
        private void TIFConsoleCMD(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if(player != null) if (!player.IsAdmin) return;
            if (!arg.HasArgs(1)) {
                Puts(LanguageEn ? "Use the correct syntax : tinfo Steam64ID" : "Используйте корректный синтаксис : tinfo Steam64ID");
                return;
            }
            String userID = arg.Args[0];
            if (!userID.IsSteamId()) {
                Puts(LanguageEn ? "The Steam64ID is specified incorrectly" : "Неверно указан Steam64ID");
                return;
            }
            PlayerInfo pData = PlayerInfo.Get(userID);
            if (pData == null) {
                Puts(LanguageEn ? "Such a player does not exist in the database" : "Такой игрок не существует в базе данных");
                return;
            }
            String cooldownInfo = pData.GetCooldown() <= 0 ? (LanguageEn ? "missing" : "отсутствует") : FormatTime(pData.GetCooldown());
            Puts(LanguageEn ? $"Information about player {userID}:\nLimits: {pData.addTeamCount}/{config.limitTeam}\nCooldown: {cooldownInfo}" : $"Информация о игроке {userID}:\nЛимиты : {pData.addTeamCount}/{config.limitTeam}\nПерезарядка : {cooldownInfo}");
        }
    }
}

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