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

FREE DiscordRewards : 0.2.2 0.2.2

Нет прав для скачивания
C#:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Ext.Discord;
using Oxide.Ext.Discord.Attributes;
using Oxide.Ext.Discord.Entities;
using Oxide.Ext.Discord.Entities.Activities;
using Oxide.Ext.Discord.Entities.Channels;
using Oxide.Ext.Discord.Entities.Gatway;
using Oxide.Ext.Discord.Entities.Gatway.Commands;
using Oxide.Ext.Discord.Entities.Guilds;
using Oxide.Ext.Discord.Entities.Messages;
using Oxide.Ext.Discord.Entities.Permissions;
using Oxide.Ext.Discord.Entities.Users;
using Oxide.Ext.Discord.Logging;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("DiscordRewards", "k1lly0u", "0.2.2")]
    [Description("Reward players with items, kits and commands for being a member of your Discord")]
    class DiscordRewards : RustPlugin {
#region Fields
        [PluginReference]
        private Plugin ImageLibrary, Kits;
        [DiscordClient]
        private DiscordClient Client;
        private DiscordGuild Guild;
        private DiscordRole NitroRole;
        private DiscordChannel ValidationChannel;
        public static DiscordRewards Instance {
            get;
            private set;
        }
        private bool isInitialized = false;
        private bool needsWipe = false;
        private int statusIndex = 0;
        private enum RewardType {
            Kit, Item, Command
        }
#endregion
#region Oxide Hooks
        private void Loaded() {
            Instance = this;
            LoadData();
        }
        protected override void LoadDefaultMessages() => lang.RegisterMessages(Messages, this);
        private void OnServerInitialized() {
            LoadImages();
            if (needsWipe) {
                if (Configuration.Token.WipeReset) WipeData();
                else if (Configuration.Token.WipeResetRewards) WipeRewardCooldowns();
            }
        }
        private void OnServerSave() => SaveData();
        private void OnPlayerConnected(BasePlayer player) {
            if (player == null) return;
            ValidateUser(player);
            UpdateStatus();
        }
        private void OnPlayerDisconnected(BasePlayer player) => UpdateStatus();
        private void OnNewSave(string filename) => needsWipe = true;
        private void Unload() {
            foreach (BasePlayer player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, UI_MENU);
            if (Client != null) Client.Disconnect();
            Instance = null;
        }
#endregion
#region Discord Hooks
        private void OnDiscordClientCreated() {
            if (string.IsNullOrEmpty(Configuration.Settings.APIKey)) {
                PrintError("No API token set in config...Unable to continue!");
                return;
            }
            if (string.IsNullOrEmpty(Configuration.Settings.BotID)) {
                PrintError("No bot client ID set in config...Unable to continue!");
                return;
            }
            Puts("Establishing connection to your Discord server...");
            DiscordSettings settings = new DiscordSettings();
            settings.ApiToken = Configuration.Settings.APIKey;
            settings.LogLevel = Configuration.Settings.LogLevel;
            settings.Intents = GatewayIntents.Guilds | GatewayIntents.DirectMessages | GatewayIntents.GuildMessages | GatewayIntents.GuildMembers;
            Client.Connect(settings);
        }
        private void OnDiscordGuildCreated(DiscordGuild guild) {
            if (guild == null) {
                PrintError("Failed to connect to guild.Unable to continue...");
                return;
            }
            Guild = guild;
            Puts($"Connection to {Guild.Name} established! DiscordRewards is now active");
            NitroRole = Guild.GetBoosterRole();
            if (!string.IsNullOrEmpty(Configuration.Token.ValidationChannel)) ValidationChannel = Guild.GetChannel(Configuration.Token.ValidationChannel);
            foreach (BasePlayer player in BasePlayer.activePlayerList) ValidateUser(player);
            UpdateStatus();
            isInitialized = true;
        }
        private void OnDiscordGuildMemberRemoved(GuildMember member, DiscordGuild guild) {
            ulong steamId;
            if (userData.FindByID(member.Id, out steamId)) {
                int code;
                if (userData.HasPendingToken(steamId, out code)) userData.InvalidateToken(code);
                UserData.User user = userData.GetUser(steamId);
                if (user != null) RevokeRewards(steamId, user);
            }
        }
        private void OnDiscordDirectMessageCreated(DiscordMessage message, DiscordChannel channel) {
            if (message == null || message.Author.Bot == true) return;
            int code;
            if (int.TryParse(message.Content, out code) && AttemptTokenValidation(message.Author, code)) return;
            message.Author.CreateDirectMessageChannel(Client, (DiscordChannel dmChannel) => dmChannel.CreateMessage(Client, Message("Discord.InvalidToken")));
        }
        private void OnDiscordGuildMessageCreated(DiscordMessage message, DiscordChannel channel, DiscordGuild guild) {
            if (message == null || message.Author.Bot == true) return;
            if (ValidationChannel == null || channel != ValidationChannel) return;
            int code;
            if (int.TryParse(message.Content, out code) && AttemptTokenValidation(message.Author, code)) {
                message.DeleteMessage(Client);
                return;
            }
            message.Author.CreateDirectMessageChannel(Client, (DiscordChannel dmChannel) => dmChannel.CreateMessage(Client, Message("Discord.InvalidToken")));
            message.DeleteMessage(Client);
        }
#endregion
#region Token Validation
        private bool AttemptTokenValidation(DiscordUser discordUser, int code) {
            UserData.DiscordToken token;
            if (userData.IsValidToken(code, out token)) {
                BasePlayer player = FindPlayer(token.playerId);
                if (token.expireTime < CurrentTime()) {
                    discordUser.CreateDirectMessageChannel(Client, (DiscordChannel dmChannel) => dmChannel.CreateMessage(Client, Message("Discord.TokenExpired", player?.userID ?? 0UL)));
                    userData.InvalidateToken(code);
                    return true;
                }
                if (player == null) {
                    discordUser.CreateDirectMessageChannel(Client, (DiscordChannel dmChannel) => dmChannel.CreateMessage(Client, string.Format(Message("Discord.FailedToFindPlayer", player?.userID ?? 0UL), token.playerId)));
                    return true;
                }
                if (!player.IsConnected) {
                    discordUser.CreateDirectMessageChannel(Client, (DiscordChannel dmChannel) => dmChannel.CreateMessage(Client, Message("Discord.NotOnServer", player?.userID ?? 0UL)));
                    return true;
                }
                if (player.IsDead()) {
                    discordUser.CreateDirectMessageChannel(Client, (DiscordChannel dmChannel) => dmChannel.CreateMessage(Client, Message("Discord.UserIsDead", player?.userID ?? 0UL)));
                    return true;
                }
                userData.InvalidateToken(code);
                UserData.User user = userData.GetUser(token.playerId) ?? userData.AddNewUser(token.playerId, discordUser.Id);
                user.SetExpiryDate(Configuration.Token.RevalidationInterval);
                string response = Message("Discord.ValidatedToken", player?.userID ?? 0UL);
                if (Configuration.Token.RequireRevalidation) response += $" {string.Format(Message("Discord.TokenExpires", player?.userID ?? 0UL), FormatTime(Configuration.Token.RevalidationInterval))}";
                if (Configuration.UISettings.Enabled) response += $" {Message("Discord.OpenStore", player?.userID ?? 0UL)}";
                discordUser.CreateDirectMessageChannel(Client, (DiscordChannel dmChannel) => dmChannel.CreateMessage(Client, response));
                if (player != null) {
                    player.ChatMessage(response);
                    IssueAlternativeRewards(player);
                }
                SaveData();
                UpdateStatus();
                return true;
            }
            return false;
        }
        private BasePlayer FindPlayer(ulong userId) {
            foreach (BasePlayer player in BasePlayer.activePlayerList) {
                if (player.userID.Equals(userId)) return player;
            }
            foreach (BasePlayer player in BasePlayer.sleepingPlayerList) {
                if (player.userID.Equals(userId)) return player;
            }
            return null;
        }
#endregion
#region Status
        private void UpdateStatus() {
            statusIndex += 1;
            if (statusIndex >= (Configuration.Settings.StatusMessages?.Length ?? 0)) statusIndex = 0;
            if (Client?.Bot != null) {
                if (Configuration.Settings.StatusMessages != null && Configuration.Settings.StatusMessages.Length > 0) {
                    string message = Configuration.Settings.StatusMessages[statusIndex];
                    if (!string.IsNullOrEmpty(message)) {
                        string str = message.Replace("{playersMin}", BasePlayer.activePlayerList.Count.ToString()).Replace("{playersMax}", ConVar.Server.maxplayers.ToString()).Replace("{rewardPlayers}", (!Configuration.Token.RequireRevalidation ? userData.users.Count.ToString() : userData.users.Where(x => CurrentTime() < x.Value.expireTime).Count().ToString()));
                        Client.Bot.UpdateStatus(new UpdatePresenceCommand() {
                            Activities = new List<DiscordActivity> {
                                new DiscordActivity() {
                                    Name = str, Type = ActivityType.Game
                                }
                            }
                        }
                        );
                    }
                }
            }
            timer.In(Mathf.Clamp(Configuration.Settings.StatusCycle, 60, int.MaxValue), UpdateStatus);
        }
#endregion
#region Helpers
        private GuildMember FindMember(Snowflake id) {
            foreach (GuildMember guildMember in Guild.Members.Values) {
                if (guildMember.Id.Equals(id)) return guildMember;
            }
            return null;
        }
        public DiscordRole GetRoleByID(string id) {
            if (!string.IsNullOrEmpty(id)) {
                foreach (DiscordRole role in Guild.Roles.Values) {
                    if (role.Id.ToString().Equals(id, StringComparison.OrdinalIgnoreCase)) return role;
                }
            }
            return null;
        }
        private int GenerateToken() {
            int token = UnityEngine.Random.Range(100000, 999999);
            if (userData.tokenToUser.ContainsKey(token)) return GenerateToken();
            return token;
        }
        private static double CurrentTime() => DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
        private T ParseType<T>(string type) => (T)Enum.Parse(typeof(T), type, true);
        private string FormatTime(double time) {
            TimeSpan dateDifference = TimeSpan.FromSeconds((float)time);
            int days = dateDifference.Days;
            int hours = dateDifference.Hours;
            int mins = dateDifference.Minutes;
            int secs = dateDifference.Seconds;
            if (days > 0) return string.Format("{0:00}d:{1:00}h:{2:00}m:{3:00}s", days, hours, mins, secs);
            else if (hours > 0) return string.Format("{0:00}h:{1:00}m:{2:00}s", hours, mins, secs);
            else if (mins > 0) return string.Format("{0:00}m:{1:00}s", mins, secs);
            else return string.Format("{0}s", secs);
        }
#endregion
#region Groups and Permission Helpers
        private void AddToGroup(string userId, string groupId) => permission.AddUserGroup(userId, groupId);
        private void RemoveFromGroup(string userId, string groupId) => permission.RemoveUserGroup(userId, groupId);
        private bool GroupExists(string groupId) => permission.GroupExists(groupId);
        private bool HasGroup(string userId, string groupId) => permission.UserHasGroup(userId, groupId);
        private void GrantPermission(string userId, string perm) => permission.GrantUserPermission(userId, perm, null);
        private void RevokePermission(string userId, string perm) => permission.RevokeUserPermission(userId, perm);
        private bool HasPermission(string userId, string perm) => permission.UserHasPermission(userId, perm);
        private bool PermissionExists(string userId) => permission.PermissionExists(userId);
#endregion
#region User Validation
        private void ValidateUser(BasePlayer player) {
            if (player == null) return;
            if (player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
                timer.In(3, () => ValidateUser(player));
                return;
            }
            UserData.User user;
            if (!userData.users.TryGetValue(player.userID, out user)) return;
            if (CurrentTime() > user.expireTime) {
                if (Configuration.Token.RequireRevalidation) {
                    if (Configuration.Token.AutoRevalidation) {
                        if (FindMember(user.Id) != null) {
                            user.SetExpiryDate(Configuration.Token.RevalidationInterval);
                            IssueAlternativeRewards(player);
                            SendReply(player, Message("Message.AutoValidated", player.userID));
                            return;
                        }
                    }
                    SendReply(player, Message("Message.ValidationExpired", player.userID));
                    RevokeRewards(player.userID, user);
                    return;
                }
            }
        }
#endregion
#region Rewards
        private void IssueAlternativeRewards(BasePlayer player) {
            UserData.User user;
            if (!userData.users.TryGetValue(player.userID, out user)) return;
            for (int i = 0; i < Configuration.Rewards.Groups.Length; i++) {
                string group = Configuration.Rewards.Groups[i];
                if (GroupExists(group) && !HasGroup(player.UserIDString, group)) {
                    AddToGroup(player.UserIDString, group);
                    user.groups.Add(group);
                }
            }
            for (int i = 0; i < Configuration.Rewards.Permissions.Length; i++) {
                string perm = Configuration.Rewards.Permissions[i];
                if (PermissionExists(perm) && !HasPermission(player.UserIDString, perm)) {
                    GrantPermission(player.UserIDString, perm);
                    user.permissions.Add(perm);
                }
            }
            for (int i = 0; i < Configuration.Rewards.Commands.Length; i++) {
                string cmd = Configuration.Rewards.Commands[i];
                rust.RunServerCommand(cmd.Replace("$player.id", player.UserIDString).Replace("$player.name", player.displayName).Replace("$player.x", player.transform.position.x.ToString()).Replace("$player.y", player.transform.position.y.ToString()).Replace("$player.z", player.transform.position.z.ToString()) );
            }
            if (Configuration.Rewards.Roles.Length > 0) ApplyUserRoles(user, Configuration.Rewards.Roles, true);
            if (Configuration.Rewards.RevokeRoles.Length > 0) RevokeUserRoles(user, Configuration.Rewards.RevokeRoles, false);
            Guild.GetGuildMember(Client, user.Id, (GuildMember guildMember) => {
                bool wasNitroBooster = user.isNitroBooster;
                user.isNitroBooster = NitroRole != null && guildMember.HasRole(NitroRole);
                if (user.isNitroBooster) IssueNitroRewards(player, user);
                else if (wasNitroBooster) RevokeNitroRewards(player.userID, user);
            }
            );
        }
        private void ApplyUserRoles(UserData.User user, IEnumerable<string> roles, bool storeChanges) {
            Guild.GetGuildMember(Client, user.Id, (GuildMember guildMember) => {
                bool hasAllRoles = true;
                foreach (string roleName in roles) {
                    DiscordRole discordRole = Guild.GetRole(roleName);
                    if (discordRole == null) discordRole = GetRoleByID(roleName);
                    if (discordRole != null) {
                        if (guildMember.HasRole(discordRole)) {
                            if (storeChanges) user.roles.Add(discordRole.Id);
                            continue;
                        }
                        hasAllRoles = false;
                        Guild.AddGuildMemberRole(Client, guildMember.User, discordRole);
                    }
                }
                if (!hasAllRoles) timer.In(5f, () => ApplyUserRoles(user, roles, storeChanges));
            }
            );
        }
        private void RevokeUserRoles(UserData.User user, IEnumerable<string> roles, bool storeChanges) {
            Guild.GetGuildMember(Client, user.Id, (GuildMember guildMember) => {
                bool allRolesRemoved = true;
                foreach (string roleName in roles) {
                    DiscordRole discordRole = Guild.GetRole(roleName);
                    if (discordRole == null) discordRole = GetRoleByID(roleName);
                    if (discordRole != null) {
                        if (!guildMember.HasRole(discordRole)) {
                            if (storeChanges) user.roles.Remove(discordRole.Id);
                            continue;
                        }
                        allRolesRemoved = false;
                        Guild.RemoveGuildMemberRole(Client, guildMember.User, discordRole);
                    }
                }
                if (!allRolesRemoved) timer.In(5f, () => RevokeUserRoles(user, roles, storeChanges));
            }
            );
        }
        private void IssueNitroRewards(BasePlayer player, UserData.User user) {
            for (int i = 0; i < Configuration.Rewards.NitroGroups.Length; i++) {
                string group = Configuration.Rewards.NitroGroups[i];
                if (GroupExists(group) && !HasGroup(player.UserIDString, group)) {
                    AddToGroup(player.UserIDString, group);
                    user.nitroGroups.Add(group);
                }
            }
            for (int i = 0; i < Configuration.Rewards.NitroPermissions.Length; i++) {
                string perm = Configuration.Rewards.NitroPermissions[i];
                if (PermissionExists(perm) && !HasPermission(player.UserIDString, perm)) {
                    GrantPermission(player.UserIDString, perm);
                    user.nitroPermissions.Add(perm);
                }
            }
            for (int i = 0; i < Configuration.Rewards.NitroCommands.Length; i++) {
                string cmd = Configuration.Rewards.NitroCommands[i];
                rust.RunServerCommand(cmd.Replace("$player.id", player.UserIDString).Replace("$player.name", player.displayName).Replace("$player.x", player.transform.position.x.ToString()).Replace("$player.y", player.transform.position.y.ToString()).Replace("$player.z", player.transform.position.z.ToString()));
            }
        }
        private void RevokeRewards(ulong playerId, UserData.User user) {
            foreach (string group in user.groups) RemoveFromGroup(playerId.ToString(), group);
            user.groups.Clear();
            foreach (string perm in user.permissions) RevokePermission(playerId.ToString(), perm);
            user.permissions.Clear();
            if (user.roles.Count > 0) RevokeUserRoles(user, new List<string>(user.roles), true);
            if (Configuration.Rewards.RevokeRoles.Length > 0) ApplyUserRoles(user, Configuration.Rewards.RevokeRoles, false);
            if (user.isNitroBooster) RevokeNitroRewards(playerId, user);
        }
        private void RevokeNitroRewards(ulong playerId, UserData.User user) {
            foreach (string group in user.nitroGroups) RemoveFromGroup(playerId.ToString(), group);
            user.nitroGroups.Clear();
            foreach (string perm in user.nitroPermissions) RevokePermission(playerId.ToString(), perm);
            user.nitroPermissions.Clear();
        }
#endregion
#region UI
        private const string UI_MENU = "discordstore_ui";
        private class UI {
            public static CuiElementContainer Container(string panel, UI4 dimensions, string color = "0 0 0 0.9") {
                CuiElementContainer container = new CuiElementContainer() {
                    {
                        new CuiPanel {
                            Image = {
                                Color = color, Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                            }
                            , RectTransform = {
                                AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                            }
                            , CursorEnabled = true
                        }
                        , new CuiElement().Parent = "Hud", panel.ToString()
                    }
                }
                ;
                return container;
            }
            public static void Panel(CuiElementContainer container, string panel, string color, UI4 dimensions) {
                container.Add(new CuiPanel {
                    Image = {
                        Color = color
                    }
                    , RectTransform = {
                        AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                    }
                }
                , panel);
            }
            public static void Label(CuiElementContainer container, string panel, string text, int size, UI4 dimensions, TextAnchor align = TextAnchor.MiddleCenter) {
                container.Add(new CuiLabel {
                    Text = {
                        FontSize = size, Align = align, Text = text
                    }
                    , RectTransform = {
                        AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                    }
                }
                , panel);
            }
            public static void Button(CuiElementContainer container, string panel, string color, string text, int size, UI4 dimensions, string command, TextAnchor align = TextAnchor.MiddleCenter) {
                container.Add(new CuiButton {
                    Button = {
                        Color = color, Command = command, FadeIn = 0f,
                    }
                    , RectTransform = {
                        AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                    }
                    , Text = {
                        Text = text, FontSize = size, Align = align
                    }
                }
                , panel);
            }
            public static void Image(CuiElementContainer container, string panel, string png, UI4 dimensions) {
                container.Add(new CuiElement {
                    Name = CuiHelper.GetGuid(), Parent = panel, Components = {
                        new CuiRawImageComponent {
                            Png = png
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = dimensions.GetMin(), AnchorMax = dimensions.GetMax()
                        }
                    }
                }
                );
            }
            public static string Color(string hexColor, float alpha) {
                if (hexColor.StartsWith("#")) hexColor = hexColor.TrimStart('#');
                int red = int.Parse(hexColor.Substring(0, 2), NumberStyles.AllowHexSpecifier);
                int green = int.Parse(hexColor.Substring(2, 2), NumberStyles.AllowHexSpecifier);
                int blue = int.Parse(hexColor.Substring(4, 2), NumberStyles.AllowHexSpecifier);
                return $"{(double)red / 255} {(double)green / 255} {(double)blue / 255} {alpha}";
            }
        }
        public struct UI4 {
            public float xMin, yMin, xMax, yMax;
            public UI4(float xMin, float yMin, float xMax, float yMax) {
                this.xMin = xMin;
                this.yMin = yMin;
                this.xMax = xMax;
                this.yMax = yMax;
            }
            public string GetMin() => $"{xMin} {yMin}";
            public string GetMax() => $"{xMax} {yMax}";
            private static UI4 _full;
            public static UI4 Full {
                get {
                    if (_full.Equals(default(UI4))) _full = new UI4(0, 0, 1, 1);
                    return _full;
                }
            }
        }
#endregion
#region UI Creation
        private void OpenStore(BasePlayer player) {
            if (rewardData.items.Count > 0) LoadStoreUI(player, RewardType.Item, 0);
            else if (rewardData.kits.Count > 0) LoadStoreUI(player, RewardType.Kit, 0);
            else if (rewardData.commands.Count > 0) LoadStoreUI(player, RewardType.Command, 0);
            else SendReply(player, Message("Error.NoItems", player.userID));
        }
        private void LoadStoreUI(BasePlayer player, RewardType rewardType, int page) {
            UserData.User user;
            if (!userData.users.TryGetValue(player.userID, out user)) return;
            CuiElementContainer container = UI.Container(UI_MENU, new UI4(0.3f, 0.35f, 0.7f, 0.65f));
            UI.Panel(container, UI_MENU, Configuration.UISettings.Panel.Color, new UI4(0.0075f, 0.88f, 0.9925f, 0.98f));
            UI.Label(container, UI_MENU, Message("UI.Title", player.userID), 18, new UI4(0.015f, 0.88f, 0.99f, 0.98f), TextAnchor.MiddleLeft);
            UI.Button(container, UI_MENU, Configuration.UISettings.Close.Color, "<b>×</b>", 18, new UI4(0.95f, 0.88f, 0.992f, 0.98f), "drui.exit");
            AddCategoryButtons(container, rewardType, player.userID);
            switch (rewardType) {
                case RewardType.Kit : PopulateItems<RewardData.RewardKit>(rewardData.kits, container, page * 4, player.userID, user.isNitroBooster);
                break;
                case RewardType.Item : PopulateItems<RewardData.RewardItem>(rewardData.items, container, page * 4, player.userID, user.isNitroBooster);
                break;
                case RewardType.Command : PopulateItems<RewardData.RewardCommand>(rewardData.commands, container, page * 4, player.userID, user.isNitroBooster);
                break;
            }
            AddPagination(container, rewardType, page);
            CuiHelper.DestroyUi(player, UI_MENU);
            CuiHelper.AddUi(player, container);
        }
        private void AddCategoryButtons(CuiElementContainer container, RewardType selected, ulong playerId) {
            int i = 0;
            UI4 position = TypeAlignment.Get(i);
            if (rewardData.kits.Count > 0) {
                UI.Button(container, UI_MENU, selected == RewardType.Kit ? Configuration.UISettings.Selected.Color : Configuration.UISettings.Deselected.Color, Message("UI.Kits", playerId), 12, new UI4(position.xMin, position.yMin, position.xMax, position.yMax), selected == RewardType.Kit ? "" : "drui.changepage kit 0");
                i++;
                position = TypeAlignment.Get(i);
            }
            if (rewardData.items.Count > 0) {
                UI.Button(container, UI_MENU, selected == RewardType.Item ? Configuration.UISettings.Selected.Color : Configuration.UISettings.Deselected.Color, Message("UI.Items", playerId), 12, new UI4(position.xMin, position.yMin, position.xMax, position.yMax), selected == RewardType.Item ? "" : "drui.changepage item 0");
                i++;
                position = TypeAlignment.Get(i);
            }
            if (rewardData.commands.Count > 0) {
                UI.Button(container, UI_MENU, selected == RewardType.Command ? Configuration.UISettings.Selected.Color : Configuration.UISettings.Deselected.Color, Message("UI.Commands", playerId), 12, new UI4(position.xMin, position.yMin, position.xMax, position.yMax), selected == RewardType.Command ? "" : "drui.changepage command 0");
            }
        }
        private void PopulateItems<T>(List<T> list, CuiElementContainer container, int index, ulong playerId, bool isNitroBooster) where T : RewardData.BaseReward {
            int count = 0;
            for (int i = index; i < Mathf.Min(list.Count, index + 4);
            i++) {
                RewardData.BaseReward reward = list[i];
                UI4 position = RewardAlignment.Get(count);
                reward.AddUIEntry(container, position, i, playerId, isNitroBooster);
                count++;
            }
        }
        private void AddPagination(CuiElementContainer container, RewardType rewardType, int page) {
            int max = rewardType == RewardType.Command ? rewardData.commands.Count : rewardType == RewardType.Item ? rewardData.items.Count : rewardData.kits.Count;
            if (page > 0) UI.Button(container, UI_MENU, Configuration.UISettings.Close.Color, "< < <", 12, new UI4(0.01f, 0.01f, 0.2f, 0.08f), $"drui.changepage {rewardType} {page - 1}");
            if ((page * 3) + 3 < max) UI.Button(container, UI_MENU, Configuration.UISettings.Close.Color, "> > >", 12, new UI4(0.8f, 0.01f, 0.99f, 0.08f), $"drui.changepage {rewardType} {page + 1}");
        }
#endregion
#region UI Grid Helper
        private readonly HoriztonalAlignment RewardAlignment = new HoriztonalAlignment(4, 0.0075f, 0.01f, 0.76f, 0.66f, 0.06f);
        private readonly HoriztonalAlignment TypeAlignment = new HoriztonalAlignment(5, 0.0075f, 0.01f, 0.86f, 0.08f, 0f);
        private class HoriztonalAlignment {
            private int Columns {
                get;
                set;
            }
            private float XBorder {
                get;
                set;
            }
            private float XSpacing {
                get;
                set;
            }
            private float YOffset {
                get;
                set;
            }
            private float Height {
                get;
                set;
            }
            private float YSpacing {
                get;
                set;
            }
            private float ReservedSpace {
                get;
                set;
            }
            private float Width {
                get;
                set;
            }
            internal HoriztonalAlignment(int columns, float xBorder, float xSpacing, float yOffset, float height, float ySpacing) {
                Columns = columns;
                XBorder = xBorder;
                XSpacing = xSpacing;
                YOffset = yOffset;
                Height = height;
                YSpacing = ySpacing;
                ReservedSpace = (xBorder * 2f) + (XSpacing * (columns - 1));
                Width = (1f - ReservedSpace) / columns;
            }
            internal UI4 Get(int index) {
                int rowNumber = index == 0 ? 0 : Mathf.FloorToInt(index / Columns);
                int columnNumber = index - (rowNumber * Columns);
                float offsetX = XBorder + (Width * columnNumber) + (XSpacing * columnNumber);
                float offsetY = (YOffset - (rowNumber * Height) - (YSpacing * rowNumber));
                return new UI4(offsetX, offsetY - Height, offsetX + Width, offsetY);
            }
        }
#endregion
#region UI Commands
        [ConsoleCommand("drui.changepage")]
        private void ccmdChangePage(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null) return;
            LoadStoreUI(player, ParseType<RewardType>(arg.GetString(0)), arg.GetInt(1));
        }
        [ConsoleCommand("drui.exit")]
        private void ccmdExit(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null) return;
            CuiHelper.DestroyUi(player, UI_MENU);
        }
        [ConsoleCommand("drui.claim")]
        private void ccmdClaim(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null) return;
            UserData.User user;
            if (!userData.users.TryGetValue(player.userID, out user)) return;
            int id = arg.GetInt(1);
            RewardType rewardType = ParseType<RewardType>(arg.GetString(0));
            double remaining;
            if (Configuration.Cooldown.Enabled && user.HasCooldown(out remaining)) {
                SendReply(player, string.Format(Message("Message.OnCooldownGlobal", player.userID), FormatTime(remaining)));
                return;
            }
            if (user.HasCooldown(rewardType, id, out remaining)) {
                SendReply(player, string.Format(Message("Message.OnCooldown", player.userID), FormatTime(remaining)));
                return;
            }
            RewardData.BaseReward reward;
            if (rewardType == RewardType.Command) reward = rewardData.commands[id];
            else if (rewardType == RewardType.Item) reward = rewardData.items[id];
            else reward = rewardData.kits[id];
            if (Configuration.Cooldown.Enabled) user.AddCooldown(Configuration.Cooldown.Time);
            else user.AddCooldown(rewardType, id, reward.Cooldown);
            CuiHelper.DestroyUi(player, UI_MENU);
            reward.GiveReward(player);
            SendReply(player, Message("Message.RewardGiven", player.userID));
        }
#endregion
#region Chat Commands
        [ChatCommand("discord")]
        private void cmdDiscord(BasePlayer player, string command, string[] args) {
            if (!isInitialized) return;
            UserData.User user = userData.GetUser(player.userID);
            if (user == null || (Configuration.Token.RequireRevalidation && CurrentTime() > user.expireTime)) {
                if (args.Length == 0) {
                    SendReply(player, Message("Help.Token", player.userID));
                    if (ValidationChannel != null) SendReply(player, string.Format(Message("Help.BotOrChannel", player.userID), Client.Bot.BotUser.Username, ValidationChannel.Name));
                    else SendReply(player, string.Format(Message("Help.BotOnly", player.userID), Client.Bot.BotUser.Username));
                    return;
                }
                int code;
                if (userData.HasPendingToken(player.userID, out code)) {
                    SendReply(player, string.Format(Message("Error.PendingToken", player.userID), code, Client.Bot.BotUser.Username));
                    return;
                }
                if (args[0].ToLower() == "token") {
                    code = GenerateToken();
                    userData.AddToken(code, player.userID, Configuration.Token.TokenLife);
                    SendReply(player, string.Format(Message("Message.Token", player.userID), code));
                }
                return;
            }
            if (Configuration.UISettings.Enabled) OpenStore(player);
            else SendReply(player, Message("Message.AlreadyRegistered"));
        }
#endregion
#region Console Commands
        [ConsoleCommand("discord.admin")]
        private void ccmdDiscordAdmin(ConsoleSystem.Arg arg) {
            if (arg.Connection != null && arg.Connection.authLevel != 2) return;
            string[] args = arg.Args;
            if (args == null || args.Length == 0) {
                SendReply(arg, $"{Title}  v{Version}");
                SendReply(arg, "discord.admin purge - Clear out all expired user data");
                SendReply(arg, "discord.admin wipe - Revoke rewards from all players and invalidate their tokens");
                SendReply(arg, "discord.admin revoke <player ID> - Revoke all rewards from the target player and invalidate their token");
                SendReply(arg, "discord.admin validatepermissions - Purges user data and validates user permissions to reinstate any that are missing");
                return;
            }
            switch (args[0].ToLower()) {
                case "purge" : {
                    if (!Configuration.Token.RequireRevalidation) {
                        SendReply(arg, "You can not purge the data file because you have Require Validation set to false in your config");
                        return;
                    }
                    double currentTime = CurrentTime();
                    int count = 0;
                    for (int i = userData.users.Count - 1; i >= 0; i--) {
                        KeyValuePair<ulong, UserData.User> kvp = userData.users.ElementAt(i);
                        if (currentTime > kvp.Value.expireTime || string.IsNullOrEmpty(kvp.Value.discordId)) {
                            RevokeRewards(kvp.Key, kvp.Value);
                            userData.users.Remove(kvp.Key);
                            count++;
                        }
                    }
                    SaveData();
                    UpdateStatus();
                    SendReply(arg, $"Revoked rewards and purged {count} users with expired tokens from the data file");
                }
                return;
                case "wipe" : WipeData();
                SendReply(arg, "Revoked all user rewards and wiped user data");
                return;
                case "revoke" : if (args.Length == 2) {
                    ulong playerId;
                    if (!ulong.TryParse(args[1], out playerId)) {
                        SendReply(arg, "Invalid Steam ID entered");
                        return;
                    }
                    UserData.User user;
                    if (!userData.users.TryGetValue(playerId, out user)) {
                        SendReply(arg, "The specified user does not have any data saved");
                        return;
                    }
                    RevokeRewards(playerId, user);
                    userData.users.Remove(playerId);
                    SaveData();
                    UpdateStatus();
                    SendReply(arg, $"Successfully revoked rewards for user: {playerId}");
                }
                else SendReply(arg, "You must enter a players Steam ID");
                return;
                case "validatepermissions" : {
                    int purgeCount = 0;
                    int reinstateCount = 0;
                    if (Configuration.Token.RequireRevalidation) {
                        double currentTime = CurrentTime();
                        for (int i = userData.users.Count - 1; i >= 0; i--) {
                            KeyValuePair<ulong, UserData.User> kvp = userData.users.ElementAt(i);
                            if (currentTime > kvp.Value.expireTime) {
                                RevokeRewards(kvp.Key, kvp.Value);
                                userData.users.Remove(kvp.Key);
                                purgeCount++;
                            }
                        }
                    }
                    foreach (KeyValuePair<ulong, UserData.User> kvp in userData.users) {
                        foreach(string perm in kvp.Value.permissions) {
                            if (!HasPermission(kvp.Key.ToString(), perm)) {
                                GrantPermission(kvp.Key.ToString(), perm);
                                reinstateCount++;
                            }
                        }
                    }
                    SendReply(arg, $"Purged {purgeCount} inactive users and reinstated missing permissions for {reinstateCount} users");
                }
                return;
                default : break;
            }
        }
        [ConsoleCommand("discord.rewards")]
        private void ccmdDiscordRewards(ConsoleSystem.Arg arg) {
            if (arg.Connection != null && arg.Connection.authLevel != 2) return;
            string[] args = arg.Args;
            if (args == null || args.Length == 0) {
                SendReply(arg, $"{Title}  v{Version}");
                SendReply(arg, "--- List Rewards ---");
                SendReply(arg, "discord.rewards list <items | kits | commands> - Display a list of rewards for the specified category, which information on each item");
                SendReply(arg, "--- Add Rewards ---");
                SendReply(arg, "discord.rewards add item <shortname> <skinId> <amount> <cooldown> <opt:bp> - Add a new reward item to the store (add \"bp\" to add the item as a blueprint)");
                SendReply(arg, "discord.rewards add kit <name> <kitname> <cooldown> - Add a new reward kit to the store");
                SendReply(arg, "discord.rewards add command <name> <command> <cooldown> - Add a new reward command to the store");
                SendReply(arg, "--- Editing Rewards ---");
                SendReply(arg, "discord.rewards edit item <ID> <name | amount | cooldown> \"edit value\" - Edit the specified field of the item with ID number <ID>");
                SendReply(arg, "discord.rewards edit kit <ID> <name | description | icon | cooldown> \"edit value\" - Edit the specified field of the kit with ID number <ID>");
                SendReply(arg, "discord.rewards edit command <ID> <name | amount | description | icon | add | remove | cooldown> \"edit value\" - Edit the specified field of the kit with ID number <ID>");
                SendReply(arg, "Icon field : The icon field can either be a URL, or a image saved to disk under the folder \"oxide/data/DiscordRewards/Images/\"");
                SendReply(arg, "Command add/remove field: Here you add additional commands or remove existing commands.Be sure to type the command inside quotation marks");
                SendReply(arg, "--- Removing Rewards ---");
                SendReply(arg, "discord.rewards remove item <ID #> - Removes the item with the specified ID number");
                SendReply(arg, "discord.rewards remove kit <ID #> - Removes the kit with the specified ID number");
                SendReply(arg, "discord.rewards remove command <ID #> - Removes the command with the specified ID number");
                SendReply(arg, "--- Important Note ---");
                SendReply(arg, "Removing rewards may change each rewards ID number.Be sure to list your rewards before removing them");
                SendReply(arg, "To set a reward for Nitro Boosters only add the word 'nitro' to the end of the command when adding the reward!");
                return;
            }
            bool isNitro = arg.Args.Last().ToLower() == "nitro";
            if (args.Length >= 1) {
                switch (args[0].ToLower()) {
#region Lists
                    case "list" : if (args.Length >= 2) {
                        int i = 0;
                        switch (args[1].ToLower()) {
                            case "items" : foreach (var entry in rewardData.items) {
                                SendReply(arg, string.Format("Item ID: {0} || Shortname: {1} ||  Amount: {2} || Skin ID: {3} ||Is Blueprint {4} || Cooldown : {5}", i, entry.Shortname, entry.Amount, entry.SkinID, entry.IsBP, entry.Cooldown));
                                i++;
                            }
                            return;
                            case "kits" : i = 0;
                            foreach (var entry in rewardData.kits) {
                                SendReply(arg, string.Format("Kit ID: {0} || Name: {1} || Description: {2} || Cooldown : {3}", i, entry.Kit, entry.Description, entry.Cooldown));
                                i++;
                            }
                            return;
                            case "commands" : i = 0;
                            foreach (var entry in rewardData.commands) {
                                SendReply(arg, string.Format("Command ID: {0} || Name: {1} || Description: {2} || Commands: {3} || Cooldown : {4}", i, entry.Name, entry.Description, entry.Commands.ToSentence(), entry.Cooldown));
                                i++;
                            }
                            return;
                            default : return;
                        }
                    }
                    return;
#endregion
#region Additions
                    case "add" : if (args.Length >= 2) {
                        switch (args[1].ToLower()) {
                            case "item" : if (args.Length >= 6) {
                                string shortname = args[2];
                                ulong skinId;
                                if (!ulong.TryParse(args[3], out skinId)) {
                                    SendReply(arg, "You must enter a number for the skin ID.If you dont wish to select any skin use 0");
                                    return;
                                }
                                int amount;
                                if (!int.TryParse(args[4], out amount)) {
                                    SendReply(arg, "You must enter an amount of this item");
                                    return;
                                }
                                int cooldown = 0;
                                if (!int.TryParse(args[5], out cooldown)) {
                                    SendReply(arg, "You must enter a cooldown for this item");
                                    return;
                                }
                                ItemDefinition itemDefinition = ItemManager.FindItemDefinition(shortname);
                                if (itemDefinition != null) {
                                    RewardData.RewardItem newItem = new RewardData.RewardItem {
                                        Amount = amount, Name = itemDefinition.displayName.translated, SkinID = skinId, Shortname = shortname, Cooldown = cooldown, IsBP = (args.Length >= 7 && args[6].ToLower() == "bp"), Nitro = isNitro
                                    }
                                    ;
                                    rewardData.items.Add(newItem);
                                    SendReply(arg, $"You have added {itemDefinition.displayName.english} to DiscordRewards");
                                    SaveRewards();
                                }
                                else SendReply(arg, "Invalid item selected!");
                            }
                            else SendReply(arg, "discord.rewards add item <shortname> <skinId> <amount> <cooldown> <opt:bp>");
                            return;
                            case "kit" : if (args.Length >= 5) {
                                int cooldown = 0;
                                if (!int.TryParse(args[4], out cooldown)) {
                                  
// ... [Code preview truncated due to length. Full source in attached file] ...

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