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

FREE Rules : 0.1.4 0.1.4

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6

/*
*  < ----- End-User License Agreement ----->
*  
*  You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of this software without the developer’s consent.*
*  THIS SOFTWARE IS PROVIDED BY IIIaKa AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
*  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*
*  Developer: IIIaKa
*      https://t.me/iiiaka
*      Discord: @iiiaka
*      https://github.com/IIIaKa
*      https://umod.org/user/IIIaKa
*      https://codefling.com/iiiaka
*      https://lone.design/vendor/iiiaka/
*      https://www.patreon.com/iiiaka
*      https://boosty.to/iiiaka
*  Codefling plugin page: https://codefling.com/plugins/rules
*  Codefling license: https://codefling.com/plugins/rules?tab=downloads_field_4
*  
*  Lone.Design plugin page: https://lone.design/product/rules/
*  
*  Copyright © 2023-2024 IIIaKa
*/
using System;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Libraries.Covalence;
using System.Globalization;
using UnityEngine.UI;
using Newtonsoft.Json.Converters;
namespace Oxide.Plugins {
    [Info("Rules", "IIIaKa", "0.1.4")]
    [Description("Useful Rules Agreement Plugin.Allowing you to prevent players who do not agree with your rules from playing on the server.")]
    class Rules : RustPlugin {
#region ~Variables~
        private const string PERMISSION_ADMIN = "rules.admin", PERMISSION_IGNORE = "rules.ignore";
        private const string UiName = "RulesUi", PanelName = $"{UiName}_Panel", PanelTitleName = $"{PanelName}_Title", PanelTitleTextName = $"{PanelTitleName}_Text", PanelPaginationNextParentName = $"{PanelTitleName}_Pagination_Next", PanelPaginationNextName = $"{PanelPaginationNextParentName}_Button", PanelPaginationPreviousParentName = $"{PanelTitleName}_Pagination_Previous", PanelPaginationPreviousName = $"{PanelPaginationPreviousParentName}_Button", PanelContentName = $"{PanelName}_Content", PanelContentScrollName = $"{PanelContentName}_Scroll", PanelContentProgressName = $"{PanelContentName}_Progress", ProgressFillName = $"{PanelContentProgressName}_Fill", PanelFooterName = $"{PanelName}_Footer", PanelButtonDeclineName = $"{PanelFooterName}_Decline", PanelButtonAcceptName = $"{PanelFooterName}_Accept", PanelButtonAcceptInactiveName = $"{PanelButtonAcceptName}_Inactive";
        public const string TransparentColor = "0 0 0 0", Color_1_1_1_1 = "1 1 1 1", Anchor_0_0 = "0 0", Anchor_1_1 = "1 1", Offset_0_0 = "0 0", Placeholders_TitleText = "*titleText*", Placeholders_TitleSubText = "*titleSubText*", Placeholders_DeclineBtnText = "*declineBtnText*", Placeholders_AcceptBtnText = "*acceptBtnText*";
        private bool _rulesEffect = false, _acceptEffect = false;
        private Hash<string, Timer> _awaitingPlayers = new Hash<string, Timer>();
        private DateTime _lastUpdate = DateTime.Now;
#endregion
#region ~Configuration~
        private static Configuration _config;
        private class Configuration {
            [JsonProperty(PropertyName = "Chat command")]
            public string Command = "rules";
            [JsonProperty(PropertyName = "Is it worth enabling GameTips for messages?")]
            public bool GameTips_Enabled = true;
            [JsonProperty(PropertyName = "Is it worth enabling a requirement for agreement with the rules? If disabled, the rules will not be displayed")]
            public bool Rules_Enabled = true;
            [JsonProperty(PropertyName = "Date of the last rules update.Format: yyyy-MM-dd HH:mm")]
            public string LastUpdate = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
            [JsonProperty(PropertyName = "Is it worth asking for agreement with the rules every time? If disabled, consent will only be requested again if the rules have been updated")]
            public bool EveryTime = false;
            [JsonProperty(PropertyName = "Is it worth preventing a player from using chat until they agree to the rules?")]
            public bool RestrictChat = true;
            [JsonProperty(PropertyName = "Is it worth preventing a player from using commands until they agree to the rules?")]
            public bool RestrictCommands = true;
            [JsonProperty(PropertyName = "Is it worth preventing a player from using voice chat until they agree to the rules?")]
            public bool RestrictVoice = true;
            [JsonProperty(PropertyName = "Is it worth requesting agreement from all active players with the rules after the plugin is (re)loaded or enabled?")]
            public bool ReaskOnLoad = true;
            [JsonProperty(PropertyName = "Time in seconds(0-600) given to the player to respond, after which they will be kicked/banned from the server.A value of 0 disables the time limit.")]
            public float ResponseTime = 0f;
            [JsonProperty(PropertyName = "Number of rejections(in a row) of the rules after which the player will be banned.A value of 0 disables the ban")]
            public int RejectionsToBan = 5;
            [JsonProperty(PropertyName = "Number of rules pages.Will automatically add additional language keys if they are missing")]
            public int TotalPages = 4;
            [JsonProperty(PropertyName = "Additional languages for key generation(except en and ru)")]
            public List<string> AdditionalLanguages = new List<string>();
            [JsonProperty(PropertyName = "Prefab name for the effect when requesting agreement with the rules.Leave empty to disable")]
            public string ShowRules_Sound_Prefab = "assets/bundled/prefabs/fx/invite_notice.prefab";
            [JsonProperty(PropertyName = "Prefab name for the effect upon agreement with the rules.Leave empty to disable")]
            public string Accepted_Sound_Prefab = "assets/prefabs/misc/xmas/advent_calendar/effects/open_advent.prefab";
            [JsonProperty(PropertyName = "Width of the container for the rules text, needed for scroll view calculation")]
            public float TextContainer_Width = 600f;
            [JsonProperty(PropertyName = "Height of the container for the rules text, needed for scroll view calculation")]
            public float TextContainer_Height = 375f;
            public Oxide.Core.VersionNumber Version;
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                _config = Config.ReadObject<Configuration>();
            }
            catch (Exception ex) {
                PrintError($"{ex.Message}\n\n[{Title}] Your configuration file contains an error.");
            }
            if (_config == null || _config.Version == new VersionNumber()) {
                PrintWarning("The configuration file is not found or contains errors.Creating a new one...");
                LoadDefaultConfig();
            }
            else if (_config.Version < Version) {
                PrintWarning($"Your configuration file version({_config.Version}) is outdated.Updating it to {Version}.");
                _config.Version = Version;
                PrintWarning($"The configuration file has been successfully updated to version {_config.Version}!");
            }
            if (!DateTime.TryParseExact(_config.LastUpdate, "yyyy-MM-dd HH:mm", null, DateTimeStyles.None, out _lastUpdate)) {
                PrintWarning($"Failed to convert {_config.LastUpdate} to a date.Using date {_lastUpdate}.");
                _config.LastUpdate = _lastUpdate.ToString("yyyy-MM-dd HH:mm");
            }
            _config.ResponseTime = Mathf.Clamp(_config.ResponseTime, 0f, 600f);
            _config.TotalPages = Math.Max(_config.TotalPages, 1);
            if (_config.AdditionalLanguages == null) _config.AdditionalLanguages = new List<string>();
            if (_config.AdditionalLanguages.Any()) {
                foreach (var newKey in _config.AdditionalLanguages.ToList()) {
                    if (string.IsNullOrWhiteSpace(newKey) || newKey == "ru" || newKey.Length != 2 || !newKey.All(c => char.IsLetter(c))) _config.AdditionalLanguages.Remove(newKey);
                    else _langs.Add(newKey.ToLower());
                }
            }
            else _config.AdditionalLanguages.Add(string.Empty);
            SaveConfig();
        }
        protected override void SaveConfig() => Config.WriteObject(_config);
        protected override void LoadDefaultConfig() => _config = new Configuration() {
            Version = Version
        }
        ;
#endregion
#region ~DataFile~
        private static StoredData _storedData;
        private class StoredData {
            [JsonProperty(PropertyName = "Player's Data")]
            public Dictionary<string, PlayerData> PlayersData = new Dictionary<string, PlayerData>();
        }
        public class PlayerData {
            public bool HasAgreed {
                get;
                set;
            }
            public int Declines {
                get;
                set;
            }
            public DateTime LastAgree {
                get;
                set;
            }
            public bool HasReadAll {
                get;
                set;
            }
        }
        private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, _storedData);
#endregion
#region ~Language~
        private HashSet<string> _langs = new HashSet<string>() {
            "en"
        }
        ;
        private Dictionary<string, string> _enLang = new Dictionary<string, string> {
            ["RulesNotFound"]
            = "Argument {0} not found!", ["RulesAccepted"] = "Thank you for accepting our terms! Enjoy the game!", ["RulesAcceptNotRead"] = "You haven't read all the pages!", ["RulesEnabled"] = "The requirement to agree with the rules is enabled!", ["RulesDisabled"] = "The requirement to agree with the rules is disabled!", ["RulesAlreadyEnabled"] = "The requirement to agree with the rules is already enabled!", ["RulesAlreadyDisabled"] = "The requirement to agree with the rules is already disabled!", ["RulesOnce"] = "A one-time request for agreement with the rules is enabled!", ["RulesEveryTime"] = "A one-time request for agreement with the rules is disabled!", ["RulesReAsk"] = "All players have been sent a request for agreement with the rules, depending on the settings.", ["KickReason"] = "You have been kicked because you declined our rules!", ["BanReason"] = "You have been banned because you declined our rules {0} times in a row!", ["PanelTitle"] = "Terms Of Service", ["PanelLastUpdate"] = "Last updated on <color=brown>{0} {1}, {2}</color>", ["BtnAccept"] = "Accept", ["BtnDecline"] = "Decline", ["BtnNextPage"] = ">", ["BtnPreviousPage"] = "<", ["January"] = "January", ["February"] = "February", ["March"] = "March", ["April"] = "April", ["May"] = "May", ["June"] = "June", ["July"] = "July", ["August"] = "August", ["September"] = "September", ["October"] = "October", ["November"] = "November", ["December"] = "December", ["Rules_1"] = "<b>1.Information</b>\n\n<b>1.1</b> - Lack of knowledge of the rules does not exempt you from responsibility.\n<b>1.2</b> - By playing on the server, you automatically agree to all the rules listed below.\n<b>1.3</b> - If you have already been caught using cheats/macros or exploiting on another server/project, and there is proof against you, we reserve the right to ban you without further investigation.\n<b>1.4</b> - The administration determines the punishment for a player based on the severity of the violation and the circumstances.Violators may receive a warning or a permanent ban (there is no temporary bans).Bans apply to all servers within the project.\n<b>1.5</b> - The administration does not compensate for in-game items lost due to your errors, technical server/hosting issues, game bugs, or contact with rule violators.\n<b>1.6</b> - The administration does not interfere in player-to-player relationships.You are solely responsible for the people you choose to play with, so if a player deceives you, there will be no punishments for them from us.\n<b>1.7</b> - You are responsible for all your accounts.If one account is banned, the ban applies to all your accounts.The same applies if one of your accounts has a game ban (EAC).\n<b>1.8</b> - Impersonating a member of the server's administration is prohibited.", ["Rules_2"] = "<b>2.Gameplay</b>\n\n<b>2.1</b> - It is prohibited to use/store/purchase/distribute third-party software or any other means that provide an advantage over other players.\n<b>2.2</b> - Using cheat services is forbidden.\n<b>2.3</b> - Exploiting game bugs is not allowed.\n<b>2.4</b> - Exceeding the player limit in a team is prohibited:\n<b>+</b> Alliances or truces with other players are not allowed if the total number of players involved exceeds the server's limitations;\n<b>+</b> Frequent changes of allies will be considered a rule violation, as will playing with another player while your teammate is AFK or not nearby;\n<b>+</b> Changing teammates temporarily is not allowed if the replaced teammate intends to continue playing with you;\n<b>+</b> Changing a partner is allowed if your previous partner will not be in contact with you in the future.", ["Rules_3"] = "<b>3.In-Game Chat/Voice Chat</b>\n\n<b>3.1</b> - Discussion of politics, religion, immoral, and other inappropriate topics is prohibited.\n<b>3.2</b> - Inciting national, racial, or religious hatred or insulting other players and individuals is forbidden.\n<b>3.3</b> - Posting links to third-party services and websites in the chat is not allowed.\n<b>3.4</b> - Spamming (repeatedly posting meaningless phrases or characters) or sending identical messages in a short period of time is prohibited.\n<b>3.5</b> - Selling or pretending to sell cheats/macros is not allowed.\n<b>3.6</b> - Proposing actions that lead to an unwanted server exit is prohibited.Such actions include, for example, pressing <b>alt+f4</b>, typing <b>disconnect</b> in the console, and similar actions whose meanings other players may not be aware of.\n<b>3.7</b> - The administration reserves the right to mute or block a player in the chat if they behave inappropriately or disrespectfully towards other players.\n<b>3.8</b> - Selling/buying in-game items for real currency, crypto or skins is prohibited.", ["Rules_4"] = "<b>4.In-Game Check</b>\n\n<b>4.1</b> - In-Game checks are conducted exclusively through the <b>Discord</b> program.Every player on our project must have the ability to access it for the purpose of undergoing in-game checks.\n<b>4.2</b> - Calls for in-game checks are made only through in-game notifications and never through voice or text chat.\n<b>4.3</b> - If a player leaves the server, ignores a in-game check, or refuses to participate in it, they will immediately receive a ban.\n<b>4.4</b> - Clearing your PC before a in-game check is prohibited.\n<b>4.5</b> - Refusal to provide the necessary information for the in-game check or inappropriate behavior will result in a ban.\n<b>4.6</b> - If a player is banned as a result of a in-game check (including bans for refusal, ignoring, leaving the server, and providing incorrect contact information), their entire team will also be banned.\n\n<b>+</b> You have the full right to refuse to undergo a in-game check, but in this case, you and your allies will be banned.\n<b>+</b> Leaving the server, providing incorrect contact information, and ignoring the in-game check will also be considered a refusal.\n<b>+</b> If you agree to undergo the in-game check, you automatically allow the administration to install third-party programs necessary for checking your PC(e.g., AnyDesk, RCC, etc.).\n\n<b>Appeal Process</b>\nOne month after the ban, you have the ability to submit an appeal, but only if the ban was not for cheats or macros.\nAppeals can be submitted on our website."
        }
        ;
        private Dictionary<string, string> _ruLang = new Dictionary<string, string> {
            ["RulesNotFound"]
            = "Аргумент {0} не найден!", ["RulesAccepted"] = "Спасибо, что приняли наши условия! Приятной вам игры!", ["RulesAcceptNotRead"] = "Вы не прочли все страницы!", ["RulesEnabled"] = "Требование согласия с правилами включено!", ["RulesDisabled"] = "Требование согласия с правилами выключено!", ["RulesAlreadyEnabled"] = "Требование согласия с правилами уже включено!", ["RulesAlreadyDisabled"] = "Требование согласия с правилами уже выключено!", ["RulesOnce"] = "Однократный запрос на согласие с правилами включен!", ["RulesEveryTime"] = "Однократный запрос на согласие с правилами выключен!", ["RulesReAsk"] = "Всем игрокам в зависимости от настроек был отправлен запрос на соглашение с правилами.", ["KickReason"] = "Вы были исключены, так как вы отклонили наши правила!", ["BanReason"] = "Вы были заблокированы, так как вы в {0} раз подряд отклонили наши правила!", ["PanelTitle"] = "Условия использования", ["PanelLastUpdate"] = "Последнее обновление <color=brown>{1} {0} {2} года</color>", ["BtnAccept"] = "Принимаю", ["BtnDecline"] = "Отказываюсь", ["BtnNextPage"] = ">", ["BtnPreviousPage"] = "<", ["January"] = "Января", ["February"] = "Февраля", ["March"] = "Марта", ["April"] = "Апреля", ["May"] = "Мая", ["June"] = "Июня", ["July"] = "Июля", ["August"] = "Августа", ["September"] = "Сентября", ["October"] = "Октября", ["November"] = "Ноября", ["December"] = "Декабря", ["Rules_1"] = "<b>1.Информация</b>\n\n<b>1.1</b> - Не знание правил не освобождает Вас от ответственности.\n<b>1.2</b> - Играя на сервере Вы автоматически соглашаетесь со всеми нижеперечисленными пунктами правил.\n<b>1.3</b> - Если Вы уже были замечены с читами/макросами или использованием просвета на другом сервере/проекте и на вас есть пруфы - мы имеем право забанить Вас без проверки.\n<b>1.4</b> - Администрация сама выбирает наказание для игрока в зависимости от степени нарушения и обстоятельств.Нарушитель может получить как предупреждение, так и перманентный бан(временных блокировок нет).Блокировка выдаётся на всех серверах проекта.\n<b>1.5</b> - Администрация не компенсирует игровые ценности, утраченные по причине вашей ошибки, технических проблем на сервере/хостинге, багов игры или контакта с нарушителями.\n<b>1.6</b> - Администрация не вмешивается во взаимоотношения игроков, за тех с кем вы играете ответственны только Вы, поэтому в случае если игрок вас обманет — ему ничего за это не будет.\n<b>1.7</b> - Вы несете ответственность за все свои аккаунты.Получив бан на одном аккаунте - Вы получите его и на остальных аккаунтах.То же самое будет если на одном из ваших аккаунтах имеется игровая блокировка(EAC).\n<b>1.8</b> - Запрещено выдавать себя за члена Администрации сервера.", ["Rules_2"] = "<b>2.Геймплей</b>\n\n<b>2.1</b> - Запрещено использовать/хранить/приобретать/распространять стороннее ПО или любые другие средства, позволяющие получить преимущество над другими игроками.\n<b>2.2</b> - Запрещено использование услуг читеров.\n<b>2.3</b> - Запрещено использование багов.\n<b>2.4</b> - Запрещено превышать лимит игроков в команде:\n<b>+</b> Нельзя устраивать альянсы или перемирия с другими игроками если в сумме вас больше, чем указано в ограничениях сервера;\n<b>+</b> Частая смена союзников будет считаться за нарушение правил, тоже самое касается и игру с другим игроком пока тиммейт стоит афк или не находится рядом;\n<b>+</b> Запрещена смена союзников на время, если заменяемый союзник продолжит с вами играть;\n<b>+</b> Разрешено сменить напарника, если ваш предыдущий напарник в дальнейшем не будет с вами контактировать.", ["Rules_3"] = "<b>3.Игровой Чат/Голосовой чат</b>\n\n<b>3.1</b> - Запрещено обсуждение политики, религии, аморальных и прочих неуместных тем.\n<b>3.2</b> - Запрещено разжигание национальной, расовой или религиозной ненависти или оскорбления других игроков и других людей.\n<b>3.3</b> - Запрещены ссылки в чате на сторонние сервисы и сайты.\n<b>3.4</b> - Запрещен флуд(многократное повторение бессмысленных фраз, символов) или многократное отправление одинаковых фраз за короткий промежуток времени.\n<b>3.5</b> - Запрещено продавать или делать вид что вы продаёте читы/макросы.\n<b>3.6</b> - Запрещено предлагать сделать действия, приводящие к нежеланному выходу с сервера.К таким действиям относится например нажатие <b>alt+f4</b>, прописывание <b>disconnect</b> в консоль и прочие подобные действия, о значении которых другие игроки могут не знать.\n<b>3.7</b> - Администрация оставляет за собой право выдать мут или заблокировать игрока в чате если тот ведёт себя неадекватно или некорректно по отношению к другим игрокам.\n<b>3.8</b> - Запрещена продажа/покупка игровых ценностей за реальную валюту, крипту или скины.", ["Rules_4"] = "<b>4.Игровая проверка</b>\n\n<b>4.1</b> - Проверки проходят только через программу <b>Discord</b>.Каждый игрок на нашем проекте, в обязательном порядке должен иметь возможность зайти в нее для прохождения проверки.\n<b>4.2</b> - Вызов на проверку осуществляется только через игровое оповещение и ни в коем случае не через голосовой или текстовый чат.\n<b>4.3</b> - Если игрок покинул сервер, проигнорировал проверку или отказался от неё, то он сразу получает блокировку.\n<b>4.4</b> - Запрещено чистить ПК перед проверкой.\n<b>4.5</b> - За отказ показывать нужную для проверки информацию или неадекватное поведение — вы будете заблокированы.\n<b>4.6</b> - Если по итогу(итогом считается и блокировка за отказ / игнор / выход из сервера и предоставление некорректных данных для связи) проверки игрок блокируется, то и вся его команда блокируется вместе с ним.\n\n<b>+</b> Вы имеете полное право отказаться проходить проверку, но в этом случае Вы и ваши союзники будут заблокированы.\n<b>+</b> Так же отказом от проверки будет считаться выход с сервера, предоставление некорректных контактных данных и игнорирование проверки.\n<b>+</b> Если Вы согласны пройти проверку - то автоматически разрешаете устанавливать сторонние программы нужные администрации для проверки вашего PC(AnyDesk, RCC и т.д).\n\n<b>Возможность разблокировки</b>\nЧерез месяц после блокировки можно подать апелляцию, но, только в случае если бан был получен не за читы или макросы.\nАпелляцию можно подать на нашем сайте."
        }
        ;
        protected override void LoadDefaultMessages() {
            for (int i = 1; i <= _config.TotalPages; i++) {
                string key = $"Rules_{i}";
                if (!_enLang.ContainsKey(key)) _enLang[key] = key;
                if (!_ruLang.ContainsKey(key)) _ruLang[key] = key;
            }
            foreach (var key in _langs) lang.RegisterMessages(_enLang, this, key);
            lang.RegisterMessages(_ruLang, this, "ru");
        }
#endregion
#region ~Methods~
        private void AskRules() {
            foreach (var player in BasePlayer.activePlayerList) {
                if (player.userID.IsSteamId() && !permission.UserHasPermission(player.UserIDString, PERMISSION_IGNORE) && !permission.UserHasPermission(player.UserIDString, PERMISSION_ADMIN)) ShowRules(player);
            }
        }
        private void ToggleRules(bool isUnload = false) {
            if (isUnload || !_config.Rules_Enabled) {
                Interface.CallHook("RulesDisabled");
                DestroyAllPanels();
                Unsubscribe(nameof(OnPlayerConnected));
                Unsubscribe(nameof(OnUserChat));
                Unsubscribe(nameof(OnUserCommand));
                Unsubscribe(nameof(OnPlayerVoice));
                Unsubscribe(nameof(OnUserUnbanned));
                Unsubscribe(nameof(OnUserPermissionRevoked));
                Unsubscribe(nameof(OnGroupPermissionRevoked));
            }
            else {
                _awaitingPlayers.Clear();
                Interface.CallHook("RulesEnabled");
                if (_config.ReaskOnLoad) AskRules();
                Subscribe(nameof(OnPlayerConnected));
                Subscribe(nameof(OnUserUnbanned));
                Subscribe(nameof(OnUserPermissionRevoked));
                Subscribe(nameof(OnGroupPermissionRevoked));
            }
        }
        private static void SendEffect(Vector3 position, Network.Connection connection, string prefabName) {
            var effect = new Effect();
            effect.Init(Effect.Type.Generic, position, Vector3.zero);
            effect.pooledString = prefabName;
            EffectNetwork.Send(effect, connection);
        }
        private void DestroyPanel(BasePlayer player) {
            CuiHelper.DestroyUi(player, UiName);
            if (_awaitingPlayers.TryGetValue(player.UserIDString, out var timer)) {
                if (timer != null) timer.Destroy();
                _awaitingPlayers.Remove(player.UserIDString);
            }
        }
        private void DestroyAllPanels() {
            foreach (var player in BasePlayer.activePlayerList) DestroyPanel(player);
        }
#endregion
#region ~Oxide Hooks~
        void OnPlayerConnected(BasePlayer player) {
            if (!_storedData.PlayersData.ContainsKey(player.UserIDString)) _storedData.PlayersData[player.UserIDString] = new PlayerData();
            if (!permission.UserHasPermission(player.UserIDString, PERMISSION_IGNORE) && !permission.UserHasPermission(player.UserIDString, PERMISSION_ADMIN)) ShowRules(player);
        }
        object OnUserChat(IPlayer player, string message) => _awaitingPlayers.ContainsKey(player.Id) ? false : null;
        object OnUserCommand(IPlayer player, string command, string[] args) => command != _config.Command && _awaitingPlayers.ContainsKey(player.Id) ? false : null;
        object OnPlayerVoice(BasePlayer player, Byte[] data) => _awaitingPlayers.ContainsKey(player.UserIDString) ? false : null;
        void OnUserUnbanned(string name, string id, string ipAddress) {
            if (_storedData.PlayersData.TryGetValue(id, out var playerData)) playerData.Declines = 0;
        }
        void OnUserPermissionRevoked(string id, string permName) {
            if ((permName != PERMISSION_IGNORE && permName != PERMISSION_ADMIN) || permission.UserHasPermission(id, PERMISSION_IGNORE) || permission.UserHasPermission(id, PERMISSION_ADMIN)) return;
            if (ulong.TryParse(id, out var userID) && BasePlayer.TryFindByID(userID, out var player)) ShowRules(player);
        }
        void OnGroupPermissionRevoked(string groupName, string permName) {
            if (permName != PERMISSION_IGNORE && permName != PERMISSION_ADMIN) return;
            foreach (var userStr in permission.GetUsersInGroup(groupName)) {
                var userIDString = userStr.Substring(0, userStr.IndexOf('(')).Trim();
                if (ulong.TryParse(userIDString, out var userID) && BasePlayer.TryFindByID(userID, out var player)) {
                    if (!permission.UserHasPermission(player.UserIDString, PERMISSION_IGNORE) && !permission.UserHasPermission(player.UserIDString, PERMISSION_ADMIN)) ShowRules(player);
                }
            }
        }
        void Init() {
            Unsubscribe(nameof(OnPlayerConnected));
            Unsubscribe(nameof(OnUserChat));
            Unsubscribe(nameof(OnUserCommand));
            Unsubscribe(nameof(OnPlayerVoice));
            Unsubscribe(nameof(OnUserUnbanned));
            Unsubscribe(nameof(OnUserPermissionRevoked));
            Unsubscribe(nameof(OnGroupPermissionRevoked));
            Unsubscribe(nameof(OnServerSave));
            permission.RegisterPermission(PERMISSION_IGNORE, this);
            permission.RegisterPermission(PERMISSION_ADMIN, this);
            AddCovalenceCommand(_config.Command, nameof(Rules_Command));
            _storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
        }
        void OnServerInitialized() {
            if (!string.IsNullOrWhiteSpace(_config.ShowRules_Sound_Prefab)) {
                _rulesEffect = true;
                if (!StringPool.toNumber.ContainsKey(_config.ShowRules_Sound_Prefab)) {
                    PrintError($"Effect {_config.ShowRules_Sound_Prefab} not found.Default is being used.");
                    _config.ShowRules_Sound_Prefab = "assets/bundled/prefabs/fx/invite_notice.prefab";
                    SaveConfig();
                }
            }
            if (!string.IsNullOrWhiteSpace(_config.Accepted_Sound_Prefab)) {
                _acceptEffect = true;
                if (!StringPool.toNumber.ContainsKey(_config.Accepted_Sound_Prefab)) {
                    PrintError($"Effect {_config.Accepted_Sound_Prefab} not found.Default is being used.");
                    _config.Accepted_Sound_Prefab = "assets/prefabs/misc/xmas/advent_calendar/effects/open_advent.prefab";
                    SaveConfig();
                }
            }
            InitUi();
            foreach (var player in BasePlayer.activePlayerList) {
                if (player.userID.IsSteamId() && !_storedData.PlayersData.ContainsKey(player.UserIDString)) _storedData.PlayersData[player.UserIDString] = new PlayerData();
            }
            ToggleRules();
            Subscribe(nameof(OnServerSave));
        }
        void OnServerSave() => SaveData();
#endregion
#region ~Commands~
        private void Rules_Command(IPlayer player, string command, string[] args) {
            if (args == null || args.Length < 1) return;
            string replyKey = string.Empty;
            string[] replyArgs = new string[5];
            bool isWarning = false, commandHandled = false;
            if (player.IsServer || permission.UserHasPermission(player.Id, PERMISSION_ADMIN)) {
                commandHandled = true;
                switch (args[0]) {
                    case "enable" : if (_config.Rules_Enabled) {
                        replyKey = "RulesAlreadyEnabled";
                        isWarning = true;
                    }
                    else {
                        _config.Rules_Enabled = true;
                        ToggleRules();
                        replyKey = "RulesEnabled";
                        SaveConfig();
                    }
                    break;
                    case "disable" : if (!_config.Rules_Enabled) {
                        replyKey = "RulesAlreadyDisabled";
                        isWarning = true;
                    }
                    else {
                        _config.Rules_Enabled = false;
                        ToggleRules();
                        replyKey = "RulesDisabled";
                        SaveConfig();
                    }
                    break;
                    case "once" : _config.EveryTime = !_config.EveryTime;
                    SaveConfig();
                    replyKey = _config.EveryTime ? "RulesEveryTime" : "RulesOnce";
                    break;
                    case "reask" : if (_config.Rules_Enabled) {
                        AskRules();
                        replyKey = "RulesReAsk";
                    }
                    else {
                        replyKey = "RulesDisabled";
                        isWarning = true;
                    }
                    break;
                    default : commandHandled = false;
                    replyKey = "RulesNotFound";
                    replyArgs[0] = args[0];
                    isWarning = true;
                    break;
                }
            }
            if (commandHandled) goto exit;
            if (permission.UserHasPermission(player.Id, PERMISSION_IGNORE)) return;
            else if (player.Object is BasePlayer bPlayer) {
                replyKey = string.Empty;
                isWarning = false;
                if (args[0] == "show") ShowRules(bPlayer);
                else if (_awaitingPlayers.ContainsKey(player.Id)) {
                    var playerData = _storedData.PlayersData[player.Id];
                    switch (args[0]) {
                        case "accept" : case "decline" : if (args[0] == "accept" && !playerData.HasReadAll) {
                            replyKey = "RulesAcceptNotRead";
                            isWarning = true;
                            break;
                        }
                        DestroyPanel(bPlayer);
                        if (!_awaitingPlayers.Any()) {
                            Unsubscribe(nameof(OnUserChat));
                            Unsubscribe(nameof(OnUserCommand));
                            Unsubscribe(nameof(OnPlayerVoice));
                        }
                        if (args[0] == "accept") {
                            playerData.HasAgreed = true;
                            if (Interface.CallHook("RulesAccepted", player) != null) break;
                            playerData.Declines = 0;
                            playerData.LastAgree = DateTime.Now;
                            if (_acceptEffect) SendEffect(bPlayer.transform.position, bPlayer.Connection, _config.Accepted_Sound_Prefab);
                            replyKey = "RulesAccepted";
                        }
                        else if (args[0] == "decline") {
                            playerData.HasAgreed = false;
                            playerData.Declines++;
                            if (Interface.CallHook("RulesDeclined", player, playerData.Declines, _config.RejectionsToBan) != null) break;
                            if (_config.RejectionsToBan > 0 && playerData.Declines >= _config.RejectionsToBan) player.Ban(string.Format(lang.GetMessage("BanReason", this, player.Id), playerData.Declines));
                            else player.Kick(lang.GetMessage("KickReason", this, player.Id));
                        }
                        break;
                        default : if (int.TryParse(args[0], out int page)) DrawContent(bPlayer, playerData, page);
                        break;
                    }
                }
            }
            exit : if (!string.IsNullOrWhiteSpace(replyKey)) {
                if (!player.IsServer && _config.GameTips_Enabled) player.Command("gametip.showtoast", (int)(isWarning ? GameTip.Styles.Error : GameTip.Styles.Blue_Normal), string.Format(lang.GetMessage(replyKey, this, player.Id), replyArgs), string.Empty);
                else player.Reply(string.Format(lang.GetMessage(replyKey, this, player.Id), replyArgs));
            }
        }
#endregion
#region ~Preparing UI~
        private void InitUi() {
            RulesText savedText;
            RulesButton savedBtn;
            CuiImageComponent savedImage;
            /* ~Main Panel~ */
            if (!TryGetSavedUi(Path_MainPanel, out List<CuiElement> savedElements) || !savedElements.Any()) {
                savedElements = GetDefaultMainPanel();
                SaveDefaultUi(Path_MainPanel, savedElements);
            }
            _cached_MainPanel = CuiHelper.ToJson(savedElements);
            var container = new CuiElementContainer();
            /* ~Text Title~ */
            if (!TryGetSavedUi(Path_TextTitle, out savedText)) {
                savedText = GetDefaultTextTitle();
                SaveDefaultUi(Path_TextTitle, savedText);
            }
            container.Add(new CuiLabel {
                Text = {
                    Text = Placeholders_TitleText, Font = savedText.Font, FontSize = savedText.FontSize, Color = savedText.Color, Align = savedText.Align, FadeIn = savedText.FadeIn, VerticalOverflow = savedText.VerticalOverflow
                }
                , RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = Anchor_1_1, OffsetMin = Offset_0_0, OffsetMax = Offset_0_0
                }
            }
            , PanelTitleTextName);
            /* ~Text TitleSub~ */
            if (!TryGetSavedUi(Path_TextTitleSub, out savedText)) {
                savedText = GetDefaultTextTitleSub();
                SaveDefaultUi(Path_TextTitleSub, savedText);
            }
            container.Add(new CuiLabel {
                Text = {
                    Text = Placeholders_TitleSubText, Font = savedText.Font, FontSize = savedText.FontSize, Color = savedText.Color, Align = savedText.Align, FadeIn = savedText.FadeIn, VerticalOverflow = savedText.VerticalOverflow
                }
                , RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = Anchor_1_1, OffsetMin = Offset_0_0, OffsetMax = Offset_0_0
                }
            }
            , PanelTitleTextName);
            /* ~Button Decline~ */
            if (!TryGetSavedUi(Path_ButtonDecline, out savedBtn)) {
                savedBtn = GetDefaultButtonDecline();
                SaveDefaultUi(Path_ButtonDecline, savedBtn);
            }
            container.Add(new CuiButton {
                Button = {
                    Command = $"{_config.Command} decline", Sprite = savedBtn.Button.Sprite, Material = savedBtn.Button.Material, Color = savedBtn.Button.Color, ImageType = savedBtn.Button.ImageType, FadeIn = savedBtn.Button.FadeIn
                }
                , Text = {
                    Text = Placeholders_DeclineBtnText, Font = savedBtn.Text.Font, FontSize = savedBtn.Text.FontSize, Color = savedBtn.Text.Color, Align = savedBtn.Text.Align, FadeIn = savedBtn.Text.FadeIn, VerticalOverflow = savedBtn.Text.VerticalOverflow
                }
                , RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = Anchor_1_1, OffsetMin = Offset_0_0, OffsetMax = Offset_0_0
                }
            }
            , PanelButtonDeclineName);
            /* ~Button Accept~ */
            if (!TryGetSavedUi(Path_ButtonAccept, out savedBtn)) {
                savedBtn = GetDefaultButtonAccept();
                SaveDefaultUi(Path_ButtonAccept, savedBtn);
            }
            container.Add(new CuiButton {
                Button = {
                    Command = $"{_config.Command} accept", Sprite = savedBtn.Button.Sprite, Material = savedBtn.Button.Material, Color = savedBtn.Button.Color, ImageType = savedBtn.Button.ImageType, FadeIn = savedBtn.Button.FadeIn
                }
                , Text = {
                    Text = Placeholders_AcceptBtnText, Font = savedBtn.Text.Font, FontSize = savedBtn.Text.FontSize, Color = savedBtn.Text.Color, Align = savedBtn.Text.Align, FadeIn = savedBtn.Text.FadeIn, VerticalOverflow = savedBtn.Text.VerticalOverflow
                }
                , RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = Anchor_1_1, OffsetMin = Offset_0_0, OffsetMax = Offset_0_0
                }
            }
            , PanelButtonAcceptName);
            _cached_PanelSubElements = CuiHelper.ToJson(container);
            /* ~Accept Inactive~ */
            if (!TryGetSavedUi(Path_AcceptInactive, out savedImage)) {
                savedImage = GetDefaultAcceptInactive();
                SaveDefaultUi(Path_AcceptInactive, savedImage);
            }
            _acceptInactive = savedImage;
            /* ~Button Next~ */
            if (!TryGetSavedUi(Path_ButtonNext, out savedBtn)) {
                savedBtn = GetDefaultButtonNext();
                SaveDefaultUi(Path_ButtonNext, savedBtn);
            }
            _nextBtn = savedBtn;
            /* ~Button Previous~ */
            if (!TryGetSavedUi(Path_ButtonPrevious, out savedBtn)) {
                savedBtn = GetDefaultButtonPrevious();
                SaveDefaultUi(Path_ButtonPrevious, savedBtn);
            }
            _prevBtn = savedBtn;
            /* ~Progress Fill~ */
            if (!TryGetSavedUi(Path_ProgressFill, out savedImage)) {
                savedImage = GetDefaultProgressFill();
                SaveDefaultUi(Path_ProgressFill, savedImage);
            }
            _progressFill = savedImage;
            /* ~Text Rules~ */
            if (!TryGetSavedUi(Path_TextRules, out savedText)) {
                savedText = GetDefaultTextRules();
                SaveDefaultUi(Path_TextRules, savedText);
            }
            _rulesText = savedText;
        }
        private List<CuiElement> GetDefaultMainPanel() {
            var container = new CuiElementContainer();
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = Anchor_1_1, OffsetMin = Offset_0_0, OffsetMax = Offset_0_0
                }
                , CursorEnabled = true, KeyboardEnabled = true, Image = {
                    Color = "0 0 0 0.9", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                }
            }
            , "Overlay", UiName);
            /* ~Panel~ */
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-320 -270", OffsetMax = "320 270"
                }
                , Image = {
                    Color = TransparentColor
                }
            }
            , UiName, PanelName);
            /* ~Title~ */
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "0 1", AnchorMax = Anchor_1_1, OffsetMin = "0 -60", OffsetMax = Offset_0_0
                }
                , Image = {
                    Color = "0.1 0.65 0.95 0.9"
                }
            }
            , PanelName, PanelTitleName);
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "11.5 -20", OffsetMax = "51.5 20"
                }
                , Image = {
                    Color = Color_1_1_1_1, Sprite = "assets/icons/warning.png"
                }
            }
            , PanelTitleName, $"{PanelTitleName}_Sprite");
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = Anchor_1_1, OffsetMin = "62 10", OffsetMax = "-20 -10"
                }
                , Image = {
                    Color = TransparentColor
                }
            }
            , PanelTitleName, PanelTitleTextName);
            /* ~Pagination~ */
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-70 -15", OffsetMax = "-20 15"
                }
                , Image = {
                    Color = TransparentColor
                }
            }
            , PanelTitleName, PanelPaginationNextParentName);
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-140 -15", OffsetMax = "-90 15"
                }
                , Image = {
                    Color = TransparentColor
                }
            }
            , PanelTitleName, PanelPaginationPreviousParentName);
            /* ~Content~ */
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "0 1", AnchorMax = Anchor_1_1, OffsetMin = "0 -475", OffsetMax = "0 -60"
                }
                , Image = {
                    Color = "0.9 0.9 0.9 0.7"
                }
            }
            , PanelName, PanelContentName);
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = "1 0", OffsetMin = Offset_0_0, OffsetMax = "0 2"
                }
                , Image = {
                    Color = TransparentColor
                }
            }
            , PanelContentName, PanelContentProgressName);
            /* ~Footer~ */
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = Anchor_0_0, AnchorMax = Anchor_1_1, OffsetMin = Offset_0_0, OffsetMax = "0 -475"
                }
                , Image = {
                    Color = "0.47 0.8 1 0.8"
                }
            }
            , PanelName, PanelFooterName);
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "50 -15", OffsetMax = "200 15"
                }
                , Image = {
                    Color = TransparentColor
                }
            }
            , PanelFooterName, PanelButtonDeclineName);
            container.Add(new CuiPanel {
                RectTransform = {
                    AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-200 -15", OffsetMax = "-50 15"
                }
                , Image = {
                    Color = TransparentColor
                }
            }
            , PanelFooterName, PanelButtonAcceptName);
            return container;
        }
        private RulesText GetDefaultTextTitle() {
            return new RulesText {
                Font = "RobotoCondensed-Bold.ttf", FontSize = 16, Color = Color_1_1_1_1, Align = TextAnchor.UpperLeft
            }
            ;
        }
        private RulesText GetDefaultTextTitleSub() {
            return new RulesText {
                Font = "RobotoCondensed-Regular.ttf", FontSize = 11, Color = Color_1_1_1_1, Align = TextAnchor.LowerLeft
            }
            ;
        }
        private RulesButton GetDefaultButtonDecline() {
            return new RulesButton {
                Button = {
                    Color = "0.9 0.9 0.9 0.7"
                }
                , Text = {
                    Font = "RobotoCondensed-Regular.ttf", FontSize = 14, Color = Color_1_1_1_1, Align = TextAnchor.MiddleCenter
                }
            }
            ;
        }
        private RulesButton GetDefaultButtonAccept() {
            return new RulesButton {
                Button = {
                    Color = "0.2 0.56 1 1"
                }
                , Text = {
                    Font = "RobotoCondensed-Regular.ttf", FontSize = 14, Color = Color_1_1_1_1, Align = TextAnchor.MiddleCenter
                }
            }
            ;
        }
        private CuiImageComponent GetDefaultAcceptInactive() => new CuiImageComponent {
            Color = "0.9 0.9 0.9 0.7"
        }
        ;
        private RulesButton GetDefaultButtonNext() {
            return new RulesButton {
                Button = {
                    Color = "0.9 0.9 0.9 0.7"
                }
                , Text = {
                    Font = "RobotoCondensed-Regular.ttf", FontSize = 14, Color = Color_1_1_1_1, Align = TextAnchor.MiddleCenter
                }
            }
            ;
        }
        private RulesButton GetDefaultButtonPrevious() {
            return new RulesButton {
                Button = {
                    Color = "0.9 0.9 0.9 0.7"
                }
                , Text = {
                    Font = "RobotoCondensed-Regular.ttf", FontSize = 14, Color = Color_1_1_1_1, Align
// ... [Code preview truncated due to length. Full source in attached file] ...

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