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

FREE RaidAlert : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using System;
using System.Linq;
using Random=System.Random;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using UnityEngine;
using Facepunch;
namespace Oxide.Plugins {
    [Info("RaidAlert", "Own3r", "1.0.0")]
    class RaidAlert : RustPlugin {
#region Variables
        [PluginReference]
        private Plugin Friends;
        private const string URL_SendMessage = "https://api.vk.com/method/messages.send?user_id={0}&message={1}&v=5.68&random_id={2}&access_token={3}";
        private const string URL_GetUserInfo = "https://api.vk.com/method/users.get?v=5.73&user_ids={0}&access_token={1}";
        private const string AllowPermission = "raidalert.access";
        private readonly int triggerLayer = LayerMask.GetMask("Trigger");
        private Random Rnd = new Random();
        private Dictionary<ulong, Dictionary<string, string>> UsersVk = new Dictionary<ulong, Dictionary<string, string>>();
        private Dictionary<ulong, DateTime> LastChangeVk = new Dictionary<ulong, DateTime>();
        private Dictionary<string, string> InfoMessages = new Dictionary<string, string>() {
            {
                "CMD.RA.HELP", "ДОСТУПНЫЕ КОМАНДЫ:\n/ra add \"ссылка на профиль\" - прикрепить профиль ВК\n/ra remove - открепить профиль ВК"
            }
            , {
                "CMD.RA.ADD.HELP", "Используйте /ra add \"ссылка на профиль\" чтобы прикрепить профиль ВК.\nПример: /ra add \"vk.com/durov\" или /ra add \"vk.com/id1\""
            }
            , {
                "CMD.RA.REM.HELP", "Используйте /ra remove чтобы открепить свой профиль ВК от системы оповещений о рейде."
            }
            , {
                "VK.PROFILE.ERROR.URL", "Вы указали неверную ссылку на профиль."
            }
            , {
                "VK.PROFILE.FIND.DATABASE", "Поиск профиля в базе данных социальной сети ВК..."
            }
            , {
                "VK.PROFILE.NOT.FOUND", "Указанный вами профиль не найден в базе данных социальной сети ВК.Проверьте правильность введенных данных."
            }
            , {
                "VK.PROFILE.NOT.LINKED", "Вы не прикрепляли свой профиль ВК к системе оповещений о рейде."
            }
            , {
                "VK.PROFILE.LINKED", "Ваш профиль ВК успешно прикреплен к системе оповещений о рейде."
            }
            , {
                "VK.PROFILE.WAIT", "Вам нужно подождать {0}м.прежде чем вы сможете снова сменить ссылку на профиль ВК."
            }
            , {
                "VK.PROFILE.SUCCESS.UNLINKED", "Ваш профиль ВК успешно отвязан от системы оповещений о рейде."
            }
            , {
                "VK.PROFILE.NO.ACCESS", "Сервис ВК временно недоступен.Повторите запрос позже."
            }
            , {
                "VK.PROFILE.BAN", "Ошибка отправки сообщения, указанный пользователь ВК в чёрном списке группы."
            }
            , {
                "VK.PROFILE.NO.MESSAGE", "Ошибка отправки сообщения, указанный пользователь ВК запретил приём сообщений."
            }
            , {
                "VK.PROFILE.SEND.TEST.MESSAGE", "Профиль \"{0} {1}\" в социальной сети ВК успешно найден, пытаемся отправить проверочное сообщение..."
            }
            , {
                "VK.PROFILE.ERROR.REQUEST", "При выполнении запроса произошла ошибка, сообщите о проблемах администратору."
            }
            , {
                "VK.PROFILE.ERROR.NOT.START.DIALOG", "Для подключения системы оповещений о рейде вам необходимо начать диалог с сообществом ВК.Зайдите в сообщество \"{0}\", нажмите на кнопку \"Написать сообщение\" и отправьте любое сообщение.После чего повторно используйте команду /ra add \"ссылка на профиль\""
            }
            , {
                "VK.PROFILE.REQUEST.UNKNOWN.ERROR", "При выполнении запроса произошла неизвестная ошибка, попробуйте еще раз."
            }
            , {
                "VK.PROFILE.REQUEST.WAIT.ERROR", "Ошибка ожидания выполнения запроса, попробуйте еще раз."
            }
            , {
                "VK.PROFILE.REQUEST.BLOCK.USER", "Ошибка выполнения запроса, страница указанного пользователя ВК удалена или заблокирована."
            }
            , {
                "NO.ACCESS", "У вас нет доступа к этой команде."
            }
        }
        ;
        private Dictionary<int, ulong> GetUserInfoStatus = new Dictionary<int, ulong>();
        private Dictionary<int, bool> SendMessageStatus = new Dictionary<int, bool>();
#endregion
#region HTTP
        private ulong ProcessGetUserInfoRequest(BasePlayer player, string response) {
            Dictionary<string, object> Response = JsonConvert.DeserializeObject<Dictionary<string, object>>(response, new KeyValuesConverter());
            if (Response.ContainsKey("error")) {
                Dictionary<string, object> data = Response["error"] as Dictionary<string, object>;
                if (data.ContainsKey("error_code")) {
                    var code = Convert.ToString(data["error_code"]);
                    switch (code) {
                        case "1" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return 0;
                        case "5" : PrintError("Не верный Token ключ !");
                        if (player != null) SendReply(player, InfoMessages["VK.PROFILE.ERROR.REQUEST"]);
                        return 0;
                        case "8" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return 0;
                        case "10" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return 0;
                        case "18" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.BLOCK.USER"]);
                        return 0;
                        case "113" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.NOT.FOUND"]);
                        return 0;
                        case "405" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.NO.ACCESS"]);
                        return 0;
                        case "503" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.NO.ACCESS"]);
                        return 0;
                        default : PrintWarning("Неизвестная ошибка c кодом: "+ code);
                        if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return 0;
                    }
                }
                else {
                    PrintWarning("Ошибка возвращаемой структуры данных ВК");
                    if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                    return 0;
                }
            }
            if (Response.ContainsKey("response") && (Response["response"] as List<object>).Count() > 0) {
                List<object> json = Response["response"] as List<object>;
                var data = json[0] as Dictionary<string, object>;
                ulong vkID = 0;
                string firstName = "N/A";
                string lastName = "N/A";
                if (data.ContainsKey("id")) vkID = (ulong)Convert.ToInt64(data["id"]);
                if (data.ContainsKey("first_name")) firstName = Convert.ToString(data["first_name"]);
                if (data.ContainsKey("last_name")) lastName = Convert.ToString(data["last_name"]);
                if (player != null) SendReply(player, string.Format(InfoMessages["VK.PROFILE.SEND.TEST.MESSAGE"], firstName, lastName));
                return vkID;
            }
            if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
            return 0;
        }
        private bool ProcessSendMessageRequest(BasePlayer player, string response, string success) {
            Dictionary<string, object> Response = JsonConvert.DeserializeObject<Dictionary<string, object>>(response, new KeyValuesConverter());
            if (Response.ContainsKey("error")) {
                Dictionary<string, object> data = Response["error"] as Dictionary<string, object>;
                if (data.ContainsKey("error_code")) {
                    var code = Convert.ToString(data["error_code"]);
                    switch (code) {
                        case "1" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return false;
                        case "5" : PrintError("Не верный Token ключ !");
                        if (player != null) SendReply(player, InfoMessages["VK.PROFILE.ERROR.REQUEST"]);
                        return false;
                        case "8" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return false;
                        case "10" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return false;
                        case "405" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.NO.ACCESS"]);
                        return false;
                        case "503" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.NO.ACCESS"]);
                        return false;
                        case "900" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.BAN"]);
                        return false;
                        case "901" : if (player != null) SendReply(player, string.Format(InfoMessages["VK.PROFILE.ERROR.NOT.START.DIALOG"], configData.VkGroupName));
                        return false;
                        case "902" : if (player != null) SendReply(player, InfoMessages["VK.PROFILE.NO.MESSAGE"]);
                        return false;
                        default : PrintWarning("Неизвестная ошибка c кодом: "+ code);
                        if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                        return false;
                    }
                }
                else {
                    PrintWarning("Ошибка возвращаемой структуры данных ВК");
                    if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
                    return false;
                }
            }
            if (Response.ContainsKey("response")) {
                if (player != null) SendReply(player, success);
                return true;
            }
            if (player != null) SendReply(player, InfoMessages["VK.PROFILE.REQUEST.UNKNOWN.ERROR"]);
            return false;
        }
        private void GetUserInfo(BasePlayer player, string VkUser, int ID) {
            webrequest.Enqueue(string.Format(URL_GetUserInfo, VkUser, configData.Token), null, (code, response) => {
                GetUserInfoStatus.Add(ID, ProcessGetUserInfoRequest(player, response));
            }
            , this);
        }
        private void SendMessage(BasePlayer player, ulong VkID, string Message, int ID, string success) {
            webrequest.Enqueue(string.Format(URL_SendMessage, VkID, Message, ID, configData.Token), null, (code, response) => {
                SendMessageStatus.Add(ID, ProcessSendMessageRequest(player, response, success));
            }
            , this);
        }
#endregion
#region Main
        private string TryParseVkNameOrID(string vk) {
            string vk_ = vk.ToLower();
            //попытка раcпарсить: https://vk.com/id353770849
            if ((vk_.Contains("/id")||vk_.StartsWith("id")) && vk_.Length>3) {
                string result = "";
                int count = 0;
                int startPos = 2;
                if (vk_.Contains("/id")) startPos = vk_.IndexOf("/id")+3;
                foreach(var ch in vk_) {
                    if (count >= startPos && "0123456789".IndexOf(ch)>=0) result += ch;
                    else if (count >= startPos && "0123456789".IndexOf(ch)<0) break;
                    count++;
                }
                if (string.IsNullOrEmpty(result)) return null;
                return result;
            }
            else  //попытка раcпарсить: https://vk.com/nimant_true
            if (vk_.Contains(".com/") && vk_.Length>5) {
                string result = "";
                int count = 0;
                int startPos = vk_.IndexOf(".com/")+5;
                foreach(var ch in vk_) {
                    if (count >= startPos && "_0123456789abcdefghijklmnopqrstuvwxyz".IndexOf(ch)>=0) result += ch;
                    else if (count >= startPos && "_0123456789abcdefghijklmnopqrstuvwxyz".IndexOf(ch)<0) break;
                    count++;
                }
                if (string.IsNullOrEmpty(result)) return null;
                return result;
            }
            else {
                string result = "";
                //попытка раcпарсить: 353770849 (указанный без префикса)
                bool notID = false;
                foreach(var ch in vk_) {
                    if ("0123456789".IndexOf(ch)>=0) result += ch;
                    else {
                        notID = true;
                        break;
                    }
                }
                if (!notID && !string.IsNullOrEmpty(result)) return result;
                //попытка раcпарсить: nimant_true (указанный без префикса)
                bool notName = false;
                foreach(var ch in vk_) {
                    if ("_0123456789abcdefghijklmnopqrstuvwxyz".IndexOf(ch)>=0) result += ch;
                    else {
                        notName = true;
                        break;
                    }
                }
                if (!notName && !string.IsNullOrEmpty(result)) return result;
            }
            return null;
        }
        private void TryGetUserInfo(BasePlayer player, string Vk, int random = -1, int wait = 0) {
            if (player == null) return;
            if (wait>=100) {
                SendReply(player, InfoMessages["VK.PROFILE.REQUEST.WAIT.ERROR"]);
                return;
            }
            if (wait==0) {
                SendReply(player, InfoMessages["VK.PROFILE.FIND.DATABASE"]);
                int random_ = Rnd.Next(1, int.MaxValue);
                while (GetUserInfoStatus.ContainsKey(random_)) random_ = Rnd.Next(1, int.MaxValue);
                GetUserInfo(player, Vk, random_);
                random = random_;
            }
            if (GetUserInfoStatus.ContainsKey(random)) {
                if (GetUserInfoStatus[random] > 0) TrySendTestMsg(player, GetUserInfoStatus[random]);
                GetUserInfoStatus.Remove(random);
            }
            else {
                int wait_ = wait + 1;
                int random_ = random;
                timer.Once(0.1f, ()=> TryGetUserInfo(player, Vk, random_, wait_));
            }
            return;
        }
        private void TrySendTestMsg(BasePlayer player, ulong VkID, int random = -1, int wait = 0) {
            if (player == null) return;
            if (wait>=100) {
                SendReply(player, InfoMessages["VK.PROFILE.REQUEST.WAIT.ERROR"]);
                return;
            }
            if (wait==0) {
                int random_ = Rnd.Next(1, int.MaxValue);
                while (SendMessageStatus.ContainsKey(random_)) random_ = Rnd.Next(1, int.MaxValue);
                SendMessage(player, VkID, string.Format(configData.TestMessage, configData.ServerName), random_, InfoMessages["VK.PROFILE.LINKED"]);
                random = random_;
            }
            if (SendMessageStatus.ContainsKey(random)) {
                if (SendMessageStatus[random]) {
                    if (!UsersVk.ContainsKey(player.userID)) UsersVk.Add(player.userID, new Dictionary<string, string>() {
                        {
                            "VK", VkID.ToString()
                        }
                        , {
                            "DT", ""
                        }
                    }
                    );
                    else UsersVk[player.userID] = new Dictionary<string, string>() {
                        {
                            "VK", VkID.ToString()
                        }
                        , {
                            "DT", ""
                        }
                    }
                    ;
                    if (!LastChangeVk.ContainsKey(player.userID)) LastChangeVk.Add(player.userID, DateTime.Now);
                    else LastChangeVk[player.userID] = DateTime.Now;
                    SaveData();
                    SendMessageStatus.Remove(random);
                }
            }
            else {
                int wait_ = wait + 1;
                int random_ = random;
                timer.Once(0.1f, ()=> TrySendTestMsg(player, VkID, random_, wait_));
            }
        }
        private void TrySendUnlinkMsg(BasePlayer player, ulong VkID, int random = -1, int wait = 0) {
            if (player == null) return;
            if (wait>=100) {
                SendReply(player, InfoMessages["VK.PROFILE.REQUEST.WAIT.ERROR"]);
                return;
            }
            if (wait==0) {
                int random_ = Rnd.Next(1, int.MaxValue);
                while (SendMessageStatus.ContainsKey(random_)) random_ = Rnd.Next(1, int.MaxValue);
                SendMessage(player, VkID, string.Format(configData.MessageOff, configData.ServerName), random_, InfoMessages["VK.PROFILE.SUCCESS.UNLINKED"]);
                random = random_;
            }
            if (SendMessageStatus.ContainsKey(random)) {
                if (SendMessageStatus[random]) {
                    UsersVk.Remove(player.userID);
                    SaveData();
                    SendMessageStatus.Remove(random);
                }
            }
            else {
                int wait_ = wait + 1;
                int random_ = random;
                timer.Once(0.1f, ()=> TrySendUnlinkMsg(player, VkID, random_, wait_));
            }
        }
#endregion
#region Commands
        [ChatCommand("ra")]
        private void CmdChatRA(BasePlayer player, string command, string[] args) {
            if (player==null) return;
            if(!IsHavePerm(player)) {
                SendReply(player, InfoMessages["NO.ACCESS"]);
                return;
            }
            if (args?.Length>=1) {
                if (args[0].ToLower() != "add" && args[0].ToLower() != "remove") {
                    SendReply(player, InfoMessages["CMD.RA.HELP"]);
                    return;
                }
                if (!((args.Length==2 && args[0].ToLower()=="add") || (args.Length==1 && args[0].ToLower()=="remove") || (args.Length==2 && args[0].ToLower()=="remove") )) {
                    if (args[0].ToLower()=="add") SendReply(player, InfoMessages["CMD.RA.ADD.HELP"]);
                    else SendReply(player, InfoMessages["CMD.RA.REM.HELP"]);
                    return;
                }
                if (args[0].ToLower()=="remove") {
                    if (UsersVk.ContainsKey(player.userID)) TrySendUnlinkMsg(player, (ulong)Convert.ToInt64((UsersVk[player.userID])["VK"]));
                    else SendReply(player, InfoMessages["VK.PROFILE.NOT.LINKED"]);
                    return;
                }
                if (LastChangeVk.ContainsKey(player.userID)) {
                    var min = DateTime.Now.Subtract(LastChangeVk[player.userID]).TotalMinutes;
                    if (min < configData.NextRegTime) {
                        SendReply(player, string.Format(InfoMessages["VK.PROFILE.WAIT"], (int)Math.Ceiling(min)));
                        return;
                    }
                }
                var vk = TryParseVkNameOrID(args[1]);
                if (string.IsNullOrEmpty(vk)) {
                    SendReply(player, InfoMessages["VK.PROFILE.ERROR.URL"]);
                    return;
                }
                TryGetUserInfo(player, vk);
            }
            else {
                SendReply(player, InfoMessages["CMD.RA.HELP"]);
                return;
            }
        }
#endregion
#region Raid
        private void OnEntityDeath(BaseCombatEntity entity, HitInfo hitInfo) {
            if (hitInfo == null || entity == null) return;
            if (hitInfo.Initiator != null) {
                BasePlayer initiator = hitInfo.Initiator.ToPlayer();
                if (initiator is BasePlayer) if (IsEntityRaidable(entity)) CheckAndSendInfo(initiator, entity);
            }
        }
        public bool IsEntityRaidable(BaseCombatEntity entity) {
            if (entity is BuildingBlock) if ((entity as BuildingBlock).grade.ToString() == "Twigs") return false;
            string prefabName = entity.ShortPrefabName;
            foreach (var p in configData.InfoBlocks) if (p.Key==prefabName) return true;
            return false;
        }
        private void CheckAndSendInfo(BasePlayer raider, BaseCombatEntity entity) {
            foreach(var player in GetRaidedPlayers(entity)) {
                if (IsHavePerm(player) && UsersVk.ContainsKey(player)) {
                    if (!string.IsNullOrEmpty((UsersVk[player])["DT"]) && DateTime.Now.Subtract(Convert.ToDateTime((UsersVk[player])["DT"])).TotalMinutes < configData.NextSendTime) continue;
                    if (raider.userID==player) continue;
                    if (configData.NoInfoIfFriends && Friends != null) {
                        var areFriends = Friends.CallHook("AreFriends", player, raider.userID);
                        if (areFriends != null && areFriends is bool) if (Convert.ToBoolean(areFriends)==true) continue;
                    }
                    string obj = configData.DefaultBlock;
                    if (configData.InfoBlocks.ContainsKey(entity.ShortPrefabName)) obj = configData.InfoBlocks[entity.ShortPrefabName];
                    if (BasePlayer.activePlayerList.ToList().Exists(x=>x.userID==player)) SendReply(BasePlayer.activePlayerList.ToList().Find(x=>x.userID==player), string.Format(configData.SrvRaidMessage, raider.displayName + " ("+raider.UserIDString+")", obj));
                    else {
                        int random_ = Rnd.Next(1, int.MaxValue);
                        while (SendMessageStatus.ContainsKey(random_)) random_ = Rnd.Next(1, int.MaxValue);
                        SendMessage(null, (ulong)Convert.ToInt64((UsersVk[player])["VK"]), string.Format(configData.VkRaidMessage, raider.displayName + " ("+raider.UserIDString+")", configData.ServerName, obj), random_, null);
                    }
                    (UsersVk[player])["DT"] = DateTime.Now.ToString();
                    SaveData();
                }
            }
        }
        private List<ulong> GetRaidedPlayers(BaseCombatEntity entity) {
            List<ulong> result = new List<ulong>();
            if (entity.OwnerID>0) result.Add(entity.OwnerID);
            var bp = entity.GetBuildingPrivilege();
            if (bp == null) return result;
            foreach(var player in bp.authorizedPlayers) {
                if (!result.Contains(player.userid)) result.Add(player.userid);
            }
            return result;
        }
#endregion
#region Common
        private bool IsHavePerm(BasePlayer player) {
            if (permission.UserHasPermission(player.UserIDString, AllowPermission)) return true;
            return false;
        }
        private bool IsHavePerm(ulong userID) {
            if (permission.UserHasPermission(userID.ToString(), AllowPermission)) return true;
            return false;
        }
#endregion
#region Hooks
        private void Loaded() {
            LoadVariables();
            LoadData();
            permission.RegisterPermission(AllowPermission, this);
        }
#endregion
#region Config
        private ConfigData configData;
        private class ConfigData {
            public string Token;
            public string VkGroupName;
            public string ServerName;
            public int NextSendTime;
            public double NextRegTime;
            public string TestMessage;
            public string VkRaidMessage;
            public string SrvRaidMessage;
            public string MessageOff;
            public bool NoInfoIfFriends;
            public string DefaultBlock;
            public Dictionary<string, string> InfoBlocks;
        }
        private void LoadVariables() => configData = Config.ReadObject<ConfigData>();
        protected override void LoadDefaultConfig() {
            var config = new ConfigData {
                Token = "", VkGroupName = "Test", ServerName = "Test", NextSendTime = 15, NextRegTime = 1, NoInfoIfFriends = true, TestMessage = "РЕЙД БОТ:\nВы успешно подключили систему оповещений о рейде на сервере {0}.", VkRaidMessage = "РЕЙД БОТ:\nИгрок {0} на сервере {1} разрушил ваше строение {2}.", SrvRaidMessage = "<color=#FA8072>РЕЙД БОТ:</color>\nИгрок <color=yellow>{0}</color> разрушил ваше строение <color=yellow>{1}</color>.", MessageOff = "РЕЙД БОТ:\nВы успешно отключили систему оповещений о рейде на сервере {0}.", DefaultBlock = "Строительный блок", InfoBlocks = new Dictionary<string, string>() {
                    {
                        "floor.grill", "Решетчатый настил"
                    }
                    , {
                        "door.hinged.toptier", "Бронированная дверь"
                    }
                    , {
                        "door.double.hinged.toptier", "Двойная бронированная дверь"
                    }
                    , {
                        "gates.external.high.stone", "Высокие внешние каменные ворота"
                    }
                    , {
                        "wall.external.high.stone", "Высокая внешняя каменная стена"
                    }
                    , {
                        "gates.external.high.wood", "Высокие внешние деревянные ворота"
                    }
                    , {
                        "wall.external.high", "Высокая внешняя деревянная стена"
                    }
                    , {
                        "floor.ladder.hatch", "Люк с лестницей"
                    }
                    , {
                        "shutter.metal.embrasure.a", "Металлическая горизонтальная бойница"
                    }
                    , {
                        "shutter.metal.embrasure.b", "Металлическая вертикальная бойница"
                    }
                    , {
                        "wall.window.bars.metal", "Металлические оконные решетки"
                    }
                    , {
                        "wall.frame.cell.gate", "Тюремная дверь"
                    }
                    , {
                        "wall.frame.cell", "Тюремная решетка"
                    }
                    , {
                        "wall.window.bars.toptier", "Укрепленные оконные решетки"
                    }
                    , {
                        "door.hinged.metal", "Металлическая дверь"
                    }
                    , {
                        "door.double.hinged.metal", "Двойная металлическая дверь"
                    }
                    , {
                        "door.hinged.wood", "Деревянная дверь"
                    }
                    , {
                        "door.double.hinged.wood", "Двойная деревянная дверь"
                    }
                    , {
                        "wall.frame.garagedoor", "Гаражная дверь"
                    }
                    , {
                        "wall.frame.shopfront.metal", "Металлическая витрина магазина"
                    }
                    , {
                        "foundation.triangle", "Треугольный фундамент"
                    }
                    , {
                        "foundation.steps", "Ступеньки для фундамента"
                    }
                    , {
                        "foundation", "Фундамент"
                    }
                    , {
                        "wall.frame", "Настенный каркас"
                    }
                    , {
                        "wall.window", "Оконный проём"
                    }
                    , {
                        "wall.doorway", "Дверной проём"
                    }
                    , {
                        "wall", "Стена"
                    }
                    , {
                        "floor.frame", "Потолочный каркас"
                    }
                    , {
                        "floor.triangle", "Треугольный пол"
                    }
                    , {
                        "floor", "Пол"
                    }
                    , {
                        "roof", "Крыша"
                    }
                    , {
                        "block.stair.lshape", "L-образная лестница"
                    }
                    , {
                        "block.stair.ushape", "U-образная лестница"
                    }
                    , {
                        "pillar", "Опора"
                    }
                    , {
                        "wall.low", "Низкая стена"
                    }
                }
            }
            ;
            SaveConfig(config);
            timer.Once(0.1f, ()=>SaveConfig(configData));
        }
        private void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
        private void LoadData() => UsersVk = Interface.GetMod().DataFileSystem.ReadObject<Dictionary<ulong, Dictionary<string, string>>>("RaidAlertData");
        private void SaveData() => Interface.GetMod().DataFileSystem.WriteObject("RaidAlertData", UsersVk);
#endregion
    }
}

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