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

FREE SkinDrops : 2.0.13 2.0.13

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System.Linq;
using System.Globalization;
using Newtonsoft.Json;
using UnityEngine;
using ConVar;
using Oxide.Core.Libraries;
using Color = UnityEngine.Color;
namespace Oxide.Plugins {
    [Info("SkinDrops", "Oxide Россия | xkrystalll", "2.0.13")]
    public class SkinDrops : RustPlugin {
        const bool en = false;
        private static SkinDrops _ins;
        [PluginReference]
        private Plugin ImageLibrary;
        const bool debug = false;
#region Config, data, initialization, etc.
        private PluginConfig cfg;
        public class PluginConfig {
            [JsonProperty(en ? "Disable exp gather notification?" : "Отключить уведомление о получении exp?")]
            public bool DisableExpNotify;
            [JsonProperty(en ? "Wipe exp data on server wipe?" : "Очищать дату exp при вайпе сервера?")]
            public bool WipeExpOnServerWipe;
            [JsonProperty(en ? "Access settings" : "Настройки доступа")]
            public Access _access = new Access();
            [JsonProperty(en ? "API settings" : "Настройки API")]
            public API _api = new API();
            [JsonProperty(en ? "Settings for EXP" : "Настройки выдачи EXP")]
            public EXP _exp = new EXP();
            [JsonProperty(en ? "Drops settings" : "Настройки дропсов")]
            public DROPS _drops = new DROPS();
            [JsonProperty(en ? "Advanced settings" : "Дополнительные настройки")]
            public ADVANCED _advanced = new ADVANCED();
            public class Access {
                [JsonProperty(en ? "Enable access only to players with a privilege?" : "Включить доступ только игрокам с привелегией?")]
                public bool privateuse = false;
                [JsonProperty(en ? "Access privilege" : "Привелегия доступа")]
                public string perm = "skindrops.use";
                [JsonProperty(en ? "Menu open command" : "Команда для открытия меню")]
                public string commands = "skindrops";
            }
            public class API {
                [JsonProperty(en ? "Secret key" : "Секретный ключ")]
                public string secretkey = "";
            }
            public class EXP {
                [JsonProperty(en ? "EXP at the first login to the server" : "EXP при первом входе на сервер")]
                public float defaultexp = 0f;
                [JsonProperty(en ? "Give out EXP for loot boxes?" : "Выдавать EXP за лут ящиков?")]
                public bool crates = true;
                [JsonProperty(en ? "EXP for loot boxes" : "EXP за лут ящиков", ObjectCreationHandling = ObjectCreationHandling.Replace)]
                public Dictionary<string, float> _crates = new Dictionary<string, float>() {
                    ["crate_normal_2"]
                    = 0.1f, ["crate_normal"] = 0.025f, ["crate_elite"] = 0.35f, ["codelockedhackablecrate"] = 0.55f
                }
                ;
                [JsonProperty(en ? "Give out EXP for breaking barrels?" : "Выдавать EXP за разбивание бочек?")]
                public bool barrel = true;
                [JsonProperty(en ? "EXP for breaking barrels" : "EXP за разбивание бочек", ObjectCreationHandling = ObjectCreationHandling.Replace)]
                public Dictionary<string, float> _barrel = new Dictionary<string, float>() {
                    ["loot-barrel-1"]
                    = 0.01f, ["loot-barrel-2"] = 0.01f, ["loot_barrel_1"] = 0.01f, ["loot_barrel_2"] = 0.01f, ["oil_barrel"] = 0.01f
                }
                ;
                [JsonProperty(en ? "Give out EXP for picking up resources" : "Выдавать EXP за подбор ресурсов")]
                public bool collectible = true;
                [JsonProperty(en ? "EXP for picking up resources" : "EXP за подбор ресурсов", ObjectCreationHandling = ObjectCreationHandling.Replace)]
                public Dictionary<string, float> _collectible = new Dictionary<string, float>() {
                    ["wood"]
                    = 0.01f, ["stones"] = 0.02f, ["sulfur.ore"] = 0.05f, ["metal.ore"] = 0.03f, ["cloth"] = 0.01f
                }
                ;
                [JsonProperty(en ? "Give out EXP for gather resources" : "Выдавать EXP за добычу ресурсов")]
                public bool gather = true;
                [JsonProperty(en ? "EXP for gather resources" : "EXP за добычу ресурсов", ObjectCreationHandling = ObjectCreationHandling.Replace)]
                public Dictionary<string, float> _gather = new Dictionary<string, float>() {
                    ["wood"]
                    = 0.01f, ["stones"] = 0.02f, ["sulfur.ore"] = 0.05f, ["metal.ore"] = 0.03f,
                }
                ;
                [JsonProperty(en ? "Give out EXP for killing players" : "Выдавать EXP за убийство игроков?")]
                public bool killplayer = true;
                [JsonProperty(en ? "Consider teammates?" : "Учитывать тиммейтов?")]
                public bool teammatecheck = false;
                [JsonProperty(en ? "EXP for killing players" : "EXP за убийство игроков")]
                public float killplayer_exp = 0.01f;
                [JsonProperty(en ? "Give out EXP for killing NPC" : "Выдавать EXP за убийство NPC?")]
                public bool killnpc = true;
                [JsonProperty(en ? "EXP for killing NPC" : "EXP за убийство NPC")]
                public float killnpc_exp = 0.02f;
            }
            public class DROPS {
                [JsonProperty(en ? "Minimum number of online for the start of the draw (if not needed, put 0)" : "Минимальное количество онлайна для старта розыгрыша (если не нужно, ставим 0)")]
                public int minimumonline = 0;
                [JsonProperty(en ? "How much EXP is needed for the draw" : "Сколько нужно EXP для розыгрыша")]
                public float exp = 500f;
                [JsonProperty(en ? "How much EXP a player will pay to participate" : "Сколько EXP заплатит игрок для участия")]
                public float pay = 1f;
                [JsonProperty(en ? "Random price settings (chance in %)" : "Настройки рандома цены (шанс в %)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
                public List<Price> randomprice = new List<Price>() {
                    new Price {
                        chance = 80f, min_price = 0.01f, max_price = 1f
                    }
                    , new Price {
                        chance = 10f, min_price = 1f, max_price = 2f
                    }
                    , new Price {
                        chance = 7f, min_price = 2f, max_price = 5f
                    }
                    , new Price {
                        chance = 3f, min_price = 5f, max_price = 10f
                    }
                    ,
                }
                ;
                [JsonProperty(en ? "Notify the chat about winning a skin (the message is visible to all)" : "Оповещать в чат о выигрыше скина (сообщение видно всем)")]
                public bool chatmessage = true;
                [JsonProperty(en ? "Notify the chat about winning a skin (personally to player)" : "Оповещать в чат о выигрыше скина (лично игроку)")]
                public bool player_chatmessage = true;
                [JsonProperty(en ? "Play sound when skin is won" : "Воспроизводить звук при выигрыше скина")]
                public bool sound = true;
                [JsonProperty(en ? "Sound prefab" : "Префаб звука")]
                public string soundprefab = "assets/prefabs/misc/easter/painted eggs/effects/eggpickup.prefab";
                [JsonProperty(en ? "Notify the discord about winning a skin" : "Оповещать в дискорд о выигрыше скина")]
                public bool discordmessage = false;
                [JsonProperty("Discord Webhook")]
                public string webhook = "";
                [JsonProperty(en ? "Notify admins in discord that the money ran out or a service error" : "Оповещать админов в дискорд о том что закончились деньги или ошибка сервиса")]
                public bool dlogmessage = false;
                [JsonProperty("Discord Log Webhook")]
                public string weblog = "";
            }
            public class ADVANCED {
                [JsonProperty(en ? "Show skins list" : "Показывать список скинов которые может выиграть игрок")]
                public bool showskinlist = true;
                [JsonProperty(en ? "Sorting method (1 - min. price, 2 - max. price, 3 - random)" : "Метод сортировки (1 - мин. цена, 2 - макс. цена, 3 - рандом)")]
                public int sortmethod = 2;
            }
        }
        public class Price {
            [JsonProperty(en ? "Chance" : "Шанс выпадения")]
            public float chance = 100f;
            [JsonProperty(en ? "Minimum price" : "Минимальная цена")]
            public float min_price = 0.01f;
            [JsonProperty(en ? "Maximum price" : "Максимальная цена")]
            public float max_price = 1f;
        }
        private void Init() {
            _ins = this;
            cfg = Config.ReadObject<PluginConfig>();
            //if (cfg._drops.price_min <= 0) cfg._drops.price_min = 0.01f;
            //if (cfg._drops.price_max <= cfg._drops.price_min) cfg._drops.price_max = cfg._drops.price_min + 0.01f;
            if (cfg._advanced.sortmethod != 1 && cfg._advanced.sortmethod != 2 && cfg._advanced.sortmethod != 3) cfg._advanced.sortmethod = 1;
            if (cfg._drops.randomprice == null || cfg._drops.randomprice.Count < 1) {
                cfg._drops.randomprice = new List<Price>() {
                    new Price {
                        chance = 80f, min_price = 0.01f, max_price = 1f
                    }
                    , new Price {
                        chance = 10f, min_price = 1f, max_price = 2f
                    }
                    , new Price {
                        chance = 7f, min_price = 2f, max_price = 5f
                    }
                    , new Price {
                        chance = 3f, min_price = 5f, max_price = 10f
                    }
                    ,
                }
                ;
            }
            Config.WriteObject(cfg);
            LoadData();
        }
        private void Unload() {
            foreach (var player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, Layer);
            SaveData();
            _ins = null;
        }
        private void OnServerSave() {
            SaveData();
        }
        private void OnNewSave() {
            if (cfg.WipeExpOnServerWipe) {
                WipeEXP();
                SaveData();
                PrintWarning("Data was wiped successfully!");
            }
        }
        protected override void LoadDefaultConfig() {
            Config.WriteObject(new PluginConfig(), true);
        }
        public Dictionary<ulong, Data> PlayerData = new Dictionary<ulong, Data>();
        public List<Draw> DrawData = new List<Draw>();
        public class Draw {
            public string winnername;
            public ulong winnner;
            public string image;
            public string name;
        }
        public class Data {
            public float EXP;
            public string tradeurl;
            public string playername;
            public List<Skin> inventory = new List<Skin>();
        }
        public class Skin {
            public string techname;
            public string skinname;
            public string url;
            public int price = 0;
            public float min;
            public float max;
        }
        private void SaveData() {
            Interface.Oxide.DataFileSystem.WriteObject($"{Title}/PlayerData", PlayerData);
            Interface.Oxide.DataFileSystem.WriteObject($"{Title}/Draws", DrawData);
            Interface.Oxide.DataFileSystem.WriteObject($"{Title}/ActiveDraw", users);
        }
        private void LoadData() {
            try {
                DrawData = Interface.Oxide.DataFileSystem.ReadObject<List<Draw>>($"{Title}/Draws");
                PlayerData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, Data>>($"{Title}/PlayerData");
                users = Interface.Oxide.DataFileSystem.ReadObject<List<ulong>>($"{Title}/ActiveDraw");
            }
            catch (Exception e) {
                PrintError(e.ToString());
            }
            if (DrawData == null) DrawData = new List<Draw>();
            if (PlayerData == null) PlayerData = new Dictionary<ulong, Data>();
            if (users == null) users = new List<ulong>();
        }
        void OnServerInitialized() {
            if (string.IsNullOrEmpty(cfg._api.secretkey)) {
                PrintError(en ? "Specify the secret key in the plugin configuration" : "Укажите секретный ключ в конфигурации плагина!");
                // Interface.Oxide.UnloadPlugin(Title);
                return;
            }
            TryConnectToAPI(true);
            LoadImages();
            cmd.AddChatCommand(cfg._access.commands, this, nameof(SkinsCMD));
            if (cfg._access.privateuse && !string.IsNullOrEmpty(cfg._access.perm)) permission.RegisterPermission(cfg._access.perm, this);
            foreach (var player in BasePlayer.activePlayerList) OnPlayerConnected(player);
        }
        void OnPlayerConnected(BasePlayer player) {
            if (player.IsReceivingSnapshot) {
                NextTick(() => OnPlayerConnected(player));
                return;
            }
            if (!PlayerData.ContainsKey(player.userID)) PlayerData.Add(player.userID, new Data {
                EXP = cfg._exp.defaultexp, playername = player.displayName
            }
            );
            if (PlayerData[player.userID].playername != player.displayName) PlayerData[player.userID].playername = player.displayName;
        }
        void OnPlayerDisconnected(BasePlayer player) {
            if (openui.Contains(player.userID)) openui.Remove(player.userID);
        }
#endregion
#region Images
        void LoadImages() {
            if (!plugins.Exists("ImageLibrary")) {
                PrintError(en ? "The mandatory ImageLibrary plugin was not found." : "Не найден обязательный плагин ImageLibrary.");
                Interface.Oxide.UnloadPlugin(Title);
                return;
            }
            foreach (var skin in DrawData) {
                if (!ImageLibrary.Call<bool>("HasImage", skin.image + "/58fx58f")) ImageLibrary.Call("AddImage", skin.image + "/58fx58f", skin.image + "/58fx58f");
            }
            if (!ImageLibrary.Call<bool>("HasImage", "skindrops.icon")) ImageLibrary.Call("AddImage", "https://skindrops.org/storage/plugins/rust/skindrops/skindrops.icon.png", "skindrops.icon");
            if (!ImageLibrary.Call<bool>("HasImage", "skindrops.settings")) ImageLibrary.Call("AddImage", "https://skindrops.org/storage/plugins/rust/skindrops/skindrops.settings.png", "skindrops.settings");
            if (!ImageLibrary.Call<bool>("HasImage", "skindrops.notify")) ImageLibrary.Call("AddImage", "https://skindrops.org/storage/plugins/rust/skindrops/skindrops.notify.png", "skindrops.notify");
            if (!ImageLibrary.Call<bool>("HasImage", "skindrops.unknownuser")) ImageLibrary.Call("AddImage", "https://skindrops.org/storage/plugins/rust/skindrops/skindrops.unknownuser.png", "skindrops.unknownuser");
        }
#endregion
#region EXP hooks
        void OnPlayerDeath(BasePlayer player, HitInfo info) {
            if (player == null || info == null) return;
            if (info.InitiatorPlayer == null) return;
            if (info.InitiatorPlayer.IsNpc) return;
            if (player.IsNpc && cfg._exp.killnpc) {
                var killer = info.InitiatorPlayer;
                if (killer != null) {
                    if (killer != player) GiveEXP(killer.userID, cfg._exp.killnpc_exp);
                }
            }
            else if (cfg._exp.killplayer) {
                var killer = info.InitiatorPlayer;
                if (killer != null) {
                    if (!cfg._exp.teammatecheck) {
                        if (player.Team != null && killer.Team != null && player.Team == killer.Team) return;
                    }
                    if (killer != player) {
                        if (!player.IsNpc) GiveEXP(killer.userID, cfg._exp.killplayer_exp);
                    }
                }
            }
        }
        public List<NetworkableId> LootedBoxes = new List<NetworkableId>();
        private void OnLootEntity(BasePlayer player, BaseEntity entity) {
            if (player == null || entity == null || entity.net == null || !cfg._exp.crates) return;
            if (player.IsNpc) return;
            if (!cfg._exp._crates.ContainsKey(entity.ShortPrefabName)) return;
            if (LootedBoxes.Contains(entity.net.ID)) return;
            GiveEXP(player.userID, cfg._exp._crates[entity.ShortPrefabName]);
            if (!LootedBoxes.Contains(entity.net.ID)) LootedBoxes.Add(entity.net.ID);
        }
        void OnCollectiblePickup(CollectibleEntity collectible, BasePlayer player) {
            if (player == null || collectible == null || collectible.itemList == null || !cfg._exp.collectible) return;
            foreach (var item in collectible.itemList) {
                if (!cfg._exp._collectible.ContainsKey(item.itemDef.shortname)) return;
                GiveEXP(player.userID, cfg._exp._collectible[item.itemDef.shortname]);
            }
        }
        void OnGrowableGathered(GrowableEntity collectible, Item item, BasePlayer player) {
            if (player == null || collectible == null || item == null || !cfg._exp.collectible) return;
            if (!cfg._exp._collectible.ContainsKey(item.info.shortname)) return;
            GiveEXP(player.userID, cfg._exp._collectible[item.info.shortname]);
        }
        void OnDispenserBonus(ResourceDispenser dispenser, BasePlayer player, Item item) {
            if (dispenser == null || player == null || item == null || !cfg._exp.gather) return;
            if (!cfg._exp._gather.ContainsKey(item.info.shortname)) return;
            GiveEXP(player.userID, cfg._exp._gather[item.info.shortname]);
        }
        void OnEntityDeath(BaseEntity entity, HitInfo info) {
            if (entity == null || info == null || info.InitiatorPlayer == null) return;
            if (cfg._exp.barrel && cfg._exp._barrel.ContainsKey(entity.ShortPrefabName)) GiveEXP(info.InitiatorPlayer.userID, cfg._exp._barrel[entity.ShortPrefabName]);
        }
#endregion
#region Commands
        [ConsoleCommand("skindrops.giveskinbyname")]
        private void cmdGiveSkinByName(ConsoleSystem.Arg arg) {
            if (arg.Player() != null) if (!arg.Player().IsAdmin) return;
            if (!arg.HasArgs(2)) {
                PrintError("Usage: skindrops.giveskinbyname %STEAMID% %ITEM_NAME_FROM_SITE%");
                return;
            }
            if (!ulong.TryParse(arg.Args[0], out var targetId)) {
                PrintError("Wrong player ID!");
                return;
            }
            if (!PlayerData.TryGetValue(targetId, out var playerData)) {
                PrintError($"Player {targetId} not found in data!");
                return;
            }
            if (string.IsNullOrEmpty(playerData.tradeurl)) {
                PrintError($"Player {targetId} not configured their trade URL!");
                return;
            }
            var skinName = string.Join(" ", arg.Args.Skip(1));
            Dictionary<string, string> headers = new Dictionary<string, string> {
                {
                    "Authorization", $"Bearer {cfg._api.secretkey}"
                }
            }
            ;
            webrequest.Enqueue(api + "offers/create?" + playerData.tradeurl.Replace("https://steamcommunity.com/tradeoffer/new/?", "") + "&name=" + skinName.Replace(" ", "%20") + "&game=rust", null, (code, response) => {
                if (code != 200) {
                    PrintError($"Error on sending request. Please, contact with us");
                    return;
                }
                var json = JsonConvert.DeserializeObject<Dictionary<string, object>>(response);
                if ((bool)(json["success"]) != true) {
                    PrintError($"Error on sending request. Please, contact with us!\nError: {json["message"]}");
                    return;
                }
                PrintWarning($"Gived skin {skinName} to player {targetId}");
            }
            , this, RequestMethod.GET, headers);
        }
        void SkinsCMD(BasePlayer player, string command, string[] args) {
            if (player == null) return;
            if (cfg._access.privateuse && !permission.UserHasPermission(player.UserIDString, cfg._access.perm)) {
                ChatMessage(player, GetMsg("NO_PERM", player.UserIDString));
                return;
            }
            if (args.Length > 1) {
                if (args[0] == "wipe") {
                    if (player.IsAdmin) {
                        WipeEXP();
                        ChatMessage(player, GetMsg("EXP_WIPED", player.UserIDString));
                    }
                    else {
                        ChatMessage(player, GetMsg("NO_PERM", player.UserIDString));
                        return;
                    }
                }
            }
            DrawUI(player);
        }
        bool IsSteamID(string id) {
            if (id.StartsWith("7656")) return true;
            return false;
        }
        [ConsoleCommand("skindrops.giveskin")]
        private void GiveSkin(ConsoleSystem.Arg args) {
            if (args.Args.Length < 1) return;
            if (!args.IsAdmin) return;
            if (!IsSteamID(args.Args[0])) {
                PrintError("Enter valid steamid to give skin");
                return;
            }
            ulong winner = ulong.Parse(args.Args[0]);
            if (!PlayerData.ContainsKey(winner)) PlayerData.Add(winner, new Data {
                playername = "???"
            }
            );
            if (args.Args.Length > 1) {
                if (!float.TryParse(args.Args.ElementAtOrDefault(1)?.Replace(",", "."), out var minPrice)) {
                    PrintError("Invalid min-max price range. Usage: skindrops.giveskin <userid> <minprice> <maxprice>");
                    return;
                }
                if (!float.TryParse(args.Args.ElementAtOrDefault(2)?.Replace(",", "."), out var maxPrice)) {
                    PrintError("Invalid min-max price range. Usage: skindrops.giveskin <userid> <minprice> <maxprice>");
                    return;
                }
                if (minPrice > maxPrice) {
                    PrintError($"Min price ({minPrice}) must be greater than max price ({maxPrice}). Usage: skindrops.giveskin <userid> <minprice> <maxprice>");
                    return;
                }
                if (maxPrice - minPrice < 0.2f) {
                    PrintError($"Price range must be >= 0.2. Now - {maxPrice - minPrice}");
                    return;
                }
                if (minPrice < 0.1f) {
                    PrintError($"Price must be greater than 0.1!");
                    return;
                }
                var rangedPrice = new Price {
                    chance = 100, min_price = minPrice, max_price = maxPrice
                }
                ;
                if (rangedPrice == null) {
                    if (debug) Puts("GiveSkin - price is null in ranged price method");
                    CancelDraw(true);
                    return;
                }
                if (debug) Puts($"Ranged min - {rangedPrice.min_price}, ranged max - {rangedPrice.max_price}");
                API_GetItem(winner, rangedPrice.min_price, rangedPrice.max_price);
                PrintError($"Successfully gived a skin for {winner} in ranged price | Min - {minPrice}, Max - {maxPrice}");
                return;
            }
            Price price = GetRandomPrice();
            if (price == null) {
                if (debug) Puts("GiveSkin - price is null");
                CancelDraw(true);
                return;
            }
            if (debug) Puts($"min - {price.min_price}, max - {price.max_price}");
            API_GetItem(winner, price.min_price, price.max_price);
            PrintError($"Successfully gived a skin for {winner}");
        }
        [ConsoleCommand("skindrops.wipe")]
        private void WipeCMD(ConsoleSystem.Arg args) {
            if (!args.IsAdmin) return;
            if (args.IsClientside) {
                BasePlayer player = args.Player();
                if (player == null) return;
                if (!player.IsAdmin) return;
                WipeEXP();
            }
            else {
                WipeEXP();
                PrintWarning("EXP wiped.");
            }
        }
        [ConsoleCommand("skindrops.open")]
        private void OpenPage(ConsoleSystem.Arg args) {
            BasePlayer player = args.Player();
            if (player == null) return;
            if (cfg._access.privateuse && !permission.UserHasPermission(player.UserIDString, cfg._access.perm)) return;
            if (args.Args.Length < 1) return;
            if (args.Args[0] == "drops") DrawUI(player, args.Args[0], "skins");
            if (args.Args[0] == "inventory") DrawUI(player, args.Args[0], "skins");
        }
        [ConsoleCommand("skindrops.subpage")]
        private void Subpage(ConsoleSystem.Arg args) {
            BasePlayer player = args.Player();
            if (player == null) return;
            if (cfg._access.privateuse && !permission.UserHasPermission(player.UserIDString, cfg._access.perm)) return;
            if (args.Args.Length < 1) return;
            if (args.Args[0] != "skins" && args.Args[0] != "settings") return;
            DrawUI(player, "drops", args.Args[0]);
        }
        [ConsoleCommand("skindrops.settradeurl")]
        private void SetTradeURL(ConsoleSystem.Arg args) {
            BasePlayer player = args.Player();
            if (player == null) return;
            if (cfg._access.privateuse && !permission.UserHasPermission(player.UserIDString, cfg._access.perm)) return;
            if (args.Args.Length < 1) return;
            if (args.Args[0].Contains("https://steamcommunity.com/tradeoffer/new/?partner=") && args.Args[0].Contains("&token=")) {
                if (PlayerData.ContainsKey(player.userID)) PlayerData[player.userID].tradeurl = args.Args[0];
                else PlayerData.Add(player.userID, new Data {
                    EXP = cfg._exp.defaultexp, playername = player.displayName, tradeurl = args.Args[0]
                }
                );
            }
            else {
                player.SendConsoleCommand("skindrops.close");
                ChatMessage(player, GetMsg("TRADEURL_ERROR", player.UserIDString));
                return;
            }
        }
        [ConsoleCommand("skindrops.payfordraw")]
        private void PayForDraw(ConsoleSystem.Arg args) {
            BasePlayer player = args.Player();
            if (player == null) return;
            if (cfg._access.privateuse && !permission.UserHasPermission(player.UserIDString, cfg._access.perm)) return;
            CheckValidTradeURL(player);
        }
        [ConsoleCommand("skindrops.close")]
        private void CloseUI(ConsoleSystem.Arg args) {
            BasePlayer player = args.Player();
            if (player == null) return;
            if (cfg._access.privateuse && !permission.UserHasPermission(player.UserIDString, cfg._access.perm)) return;
            if (openui.Contains(player.userID)) openui.Remove(player.userID);
            CuiHelper.DestroyUi(player, Layer);
        }
        [ConsoleCommand("skindrops.getskin")]
        private void GetSkin(ConsoleSystem.Arg args) {
            BasePlayer player = args.Player();
            if (player == null) return;
            if (args.Args.Length < 1) return;
            var name = string.Join(" ", args.Args);
            if (!PlayerData.ContainsKey(player.userID)) return;
            if (string.IsNullOrEmpty(PlayerData[player.userID].tradeurl) || !PlayerData[player.userID].tradeurl.StartsWith("https://steamcommunity.com/tradeoffer/new/?")) {
                player.SendConsoleCommand("skindrops.close");
                ChatMessage(player, GetMsg("TRADEURL_ERROR", player.UserIDString));
                return;
            }
            var data = PlayerData[player.userID].inventory;
            for (int i = 0; i < data.Count; i++) {
                var item = data[i];
                if (item == null) continue;
                if (item.skinname == name) {
                    data.Remove(item);
                    DrawUI(player, "inventory", "skins");
                    ChatMessage(player, GetMsg("CHAT_ALERT_TRADE", player.UserIDString).Replace("{0}", item.skinname));
                    player.SendConsoleCommand($"note.inv -1685290200 -1 {item.skinname}");
                    SendTradeOffer(player.userID, PlayerData[player.userID].tradeurl, item.skinname, item.min, item.max);
                    return;
                }
            }
        }
#endregion
#region Draw
        void WipeEXP() {
            foreach (var players in PlayerData) players.Value.EXP = 0;
            SaveData();
        }
        public List<ulong> users = new List<ulong>();
        void JoinDraw(BasePlayer player) {
            if (cfg._access.privateuse && !permission.UserHasPermission(player.UserIDString, cfg._access.perm)) return;
            if ((users.Count * cfg._drops.pay) >= cfg._drops.exp || users.Contains(player.userID)) return;
            if (!LoseEXP(player.userID, cfg._drops.pay)) {
                player.SendConsoleCommand("skindrops.close");
                return;
            }
            if (!users.Contains(player.userID)) users.Add(player.userID);
            if (openui.Contains(player.userID)) DrawUI(player);
            ulong winner = GetWinner();
            Price price = GetRandomPrice();
            if (price == null) {
                if (debug) Puts("JoinDraw - price is null");
                CancelDraw(true);
                return;
            }
            if (debug) Puts($"min - {price.min_price}, max - {price.max_price}");
            if ((users.Count * cfg._drops.pay) >= cfg._drops.exp) API_GetItem(winner, price.min_price, price.max_price);
        }
        void GoDraw(ulong winner, BotItem item, float minprice, float maxprice) {
            if (!PlayerData.ContainsKey(winner)) PlayerData.Add(winner, new Data());
            var player = BasePlayer.FindByID(winner);
            foreach (var p in users) {
                var players = BasePlayer.FindByID(p);
                if (players != null) CuiHelper.DestroyUi(players, Layer + "rafflebutton");
            }
            if (PlayerData.ContainsKey(winner)) {
                string techname = GenerateName(item.name);
                Skin skin = new Skin {
                    techname = techname, skinname = item.name, url = item.image + "/120fx120f", min = minprice, max = maxprice
                }
                ;
                if (!ImageLibrary.Call<bool>("HasImage", item.image + "/120fx120f")) ImageLibrary.Call("AddImage", item.image + "/120fx120f", item.image + "/120fx120f");
                if (PlayerData[winner].inventory == null) PlayerData[winner].inventory = new List<Skin> {
                    skin
                }
                ;
                else PlayerData[winner].inventory.Add(skin);
            }
            if (DrawData.Count >= 2) DrawData.RemoveAt(0);
            DrawData.Add(new Draw {
                winnner = winner, winnername = PlayerData[winner].playername, image = item.image, name = item.name
            }
            );
            if (cfg._drops.sound) {
                foreach (var players in BasePlayer.activePlayerList) SendEffect(players, cfg._drops.soundprefab);
            }
            if (cfg._drops.chatmessage) {
                foreach (var players in BasePlayer.activePlayerList) ChatMessage(players, GetMsg("CHAT_ALERT", player.UserIDString).Replace("{0}", PlayerData[winner].playername).Replace("{1}", item.name).Replace("{2}", item.price.ToString()));
            }
            if (cfg._drops.player_chatmessage && player != null) {
                ChatMessage(player, GetMsg("CHAT_ALERT_PLAYER", player.UserIDString).Replace("{0}", item.name).Replace("{1}", item.price.ToString()));
            }
            if (player != null) player.SendConsoleCommand($"note.inv -1036635990 1 {item.name}");
            if (cfg._drops.discordmessage) DMessage(PlayerData[winner].playername, winner, item.name, item.price + "$", item.image);
            users.Clear();
            timer.Once(1f, () => {
                foreach (var players in BasePlayer.activePlayerList) {
                    if (openui.Contains(players.userID)) DrawUI(players);
                }
            }
            );
        }
        void CancelDraw(bool notify = false, bool minimum = false) {
            foreach (var player in users) GiveEXP(player, cfg._drops.pay);
            if (!minimum) {
                foreach (var player in BasePlayer.activePlayerList) ChatMessage(player, GetMsg("API_NOITEMS", player.UserIDString));
            }
            else {
                foreach (var player in BasePlayer.activePlayerList) ChatMessage(player, GetMsg("API_NOPLAYERS", player.UserIDString));
            }
            users.Clear();
            if (notify) DLog();
            foreach (var player in BasePlayer.activePlayerList) if (openui.Contains(player.userID)) DrawUI(player);
        }
        ulong GetWinner() {
            ulong winner = 0;
            var list = users.Where(x => BasePlayer.FindByID(x) != null && PlayerData[x].inventory.Count < 18 && ParticipatesInDraw(x) && !string.IsNullOrEmpty(PlayerData[x].tradeurl) && PlayerData[x].tradeurl.StartsWith("https://steamcommunity.com/tradeoffer/new/?"));
            winner = list.ElementAt(Oxide.Core.Random.Range(0, list.Count()));
            return winner;
        }
        bool ParticipatesInDraw(ulong player) {
            bool part = false;
            if (cfg._access.privateuse) {
                if (!permission.UserHasPermission(player.ToString(), cfg._access.perm)) part = false;
                else part = true;
            }
            else part = true;
            return part;
        }
        void SendTradeOffer(ulong player, string offer, string item, float minprice, float maxprice) {
            TryConnectToAPI(false);
            if (!connect) {
                CancelDraw();
                DLog();
                return;
            }
            Dictionary<string, string> headers = new Dictionary<string, string> {
                {
                    "Authorization", $"Bearer {cfg._api.secretkey}"
                }
            }
            ;
            webrequest.Enqueue(api + "offers/create?" + offer.Replace("https://steamcommunity.com/tradeoffer/new/?", "") + "&name=" + item.Replace(" ", "%20") + "&game=rust", null, (code, response) => {
                Log("SendTradeOffer" + api + "offers/create?" + offer.Replace("https://steamcommunity.com/tradeoffer/new/?", "") + "&name=" + item.Replace(" ", "%20") + "&game=rust" + " - code: " + code);
                if (debug) Puts("SendTradeOffer code: " + code);
                if (code != 200) return;
                Offer myDeserializedClass = JsonConvert.DeserializeObject<Offer>(response);
                if (debug) {
                    Log("SendTradeOffer message: " + myDeserializedClass.message);
                    Log("SendTradeOffer success: " + myDeserializedClass.success);
                    Puts("SendTradeOffer message: " + myDeserializedClass.message);
                    Puts("SendTradeOffer success: " + myDeserializedClass.success);
                }
                if (!myDeserializedClass.success) {
                    if (myDeserializedClass.message == "skin_unavailable") {
                        API_GetItem(player, minprice, maxprice);
                        return;
                    }
                    if (myDeserializedClass.message == "insufficient_funds" || myDeserializedClass.message == "offer_unavailable") {
                        CancelDraw();
                        DLog();
                        return;
                    }
                    if (myDeserializedClass.message == "trade_create_error") {
                        CancelDraw();
                        DLog();
                        return;
                    }
                    return;
                }
                Puts($"SendTradeOffer - Успешно отправлен трейд игроку {player}");
                if (debug) Puts("SendTradeOffer " + $"Успешно отправлен трейд игроку {player}");
            }
            , this, Core.Libraries.RequestMethod.GET, headers);
        }
        public class Offer {
            public bool success {
                get;
                set;
            }
            public string message {
                get;
                set;
            }
        }
        float GetPrice(bool type = false) {
            float price = 0;
            if (cfg._drops.randomprice.Count < 1) return 0;
            if (type == false) {
                price = cfg._drops.randomprice.Min(p => p.min_price);
            }
            else {
                price = cfg._drops.randomprice.Max(p => p.max_price);
            }
            return price;
        }
        public Price GetRandomPrice() {
            var randomprice = cfg._drops.randomprice;
            float totalChance = randomprice.Sum(x => x.chance);
            float rand = UnityEngine.Random.Range(0f, totalChance);
            float cumulativeChance = 0;
            Price chosenPrice = null;
            foreach (Price price in randomprice) {
                cumulativeChance += price.chance;
                if (rand < cumulativeChance) {
                    chosenPrice = price;
                    break;
                }
            }
            if (chosenPrice != null) return chosenPrice;
            else return randomprice[0];
        }
        public string GenerateName(string subname) {
            var name = 0;
            name = Oxide.Core.Random.Range(0, 100000);
            return subname + name.ToString() + subname;
        }
#endregion
#region API Works
        List<Cache> skincache = new List<Cache>();
        public class Cache {
            public string image;
            public double price;
        }
        void LoadSkinCache() {
            if (!cfg._advanced.showskinlist || !connect) return;
            if (cfg._advanced.sortmethod != 1 && cfg._advanced.sortmethod != 2 && cfg._advanced.sortmethod != 3) return;
            var price_min = GetPrice(false);
            var price_max = GetPrice(true);
            if (price_min == 0 || price_max == 0) return;
            skincache.Clear();
            string apicache = api;
            if (cfg._advanced.sortmethod == 2) apicache = api + $"items?sort=-items.price&filter[items.game]=rust&filter[max_price]={price_max}&page[size]=5";
            if (cfg._advanced.sortmethod == 1) apicache = api + $"items?sort=items.price&filter[items.game]=rust&filter[min_price]={price_min}&page[size]=5";
            if (cfg._advanced.sortmethod == 3) apicache = api + $"items?sort=items.skin_id&filter[items.game]=rust&filter[min_price]={price_min}&filter[max_price]={price_max}&page[size]=30";
            Dictionary<string, string> headers = new Dictionary<string, string> {
                {
                    "Authorization", $"Bearer {cfg._api.secretkey}"
                }
            }
            ;
            webrequest.Enqueue(apicache, null, (codes, responses) => {
                Log($"LoadSkinCache + {apicache} = code {codes}");
                Log($"LoadSkinCache + {apicache} = responses {responses}");
                if (debug) Puts($"LoadSkinCache + {apicache} " + codes);
                if (debug) Puts($"LoadSkinCache + {apicache} " + responses);
                if (codes != 200) {
                    connect = false;
                    PrintError(en ? "An API connection error occurred. Contact technical support to resolve the problem" : "Произошла ошибка подключения к API. Свяжитесь с технической поддержкой для решения проблемы");
                    return;
                }
                BotItems response_deserializeds = JsonConvert.DeserializeObject<BotItems>(responses);
                if (response_deserializeds == null) {
                    connect = false;
                    Log($"LoadSkinCache + {apicache} = response_deserializeds null");
                    PrintError(en ? "An API connection error occurred. Contact technical support to resolve the problem" : "Произошла ошибка подключения к API. Свяжитесь с технической поддержкой для решения проблемы");
                    return;
                }
                if (response_deserializeds.items.Count < 5) {
                    Log($"LoadSkinCache + {apicache} = response_deserializeds response_deserializeds.items.Count {response_deserializeds.items.Count}");
                    PrintError(en ? "Failed to load cache of playable skins" : "Не удалось загрузить кэш разыгрываемых скинов");
                    cfg._advanced.showskinlist = false;
                    return;
                }
                List<BotItem> list = null;
                if (cfg._advanced.sortmethod == 3) {
                    list = response_deserializeds.items.GroupBy(x => x.name) .Select(g => g.First()) .ToList().Take(5).ToList();
                }
                else list = response_deserializeds.items;
                foreach (var item in list) {
                    skincache.Add(new Cache {
                        image = item.image, price = item.price
                    }
                    );
                    ImageLibrary.Call("AddImage", item.image + "/145fx145f", item.image + "/145fx145f");
                }
                Log($"Successfully obtained cache of skins to be played");
                PrintWarning(en ? "Successfully obtained cache of skins to be played" : "Успешно получен кэш разыгрываемых скинов");
            }
            , this, Core.Libraries.RequestMethod.GET, headers);
        }
        bool connect = false;
        string api = "https://skindrops.org/api/v1/";
        Timer timers = null;
        int tryes = 0;
        void TryConnectToAPI(bool init = false) {
            if (string.IsNullOrEmpty(cfg._api.secretkey)) {
                PrintError(en ? "Specify the secret key in the plugin configuration" : "Укажите секретный ключ в конфигурации плагина!");
                Interface.Oxide.UnloadPlugin(Title);
                return;
            }
            if (init) PrintWarning(en ? "Trying to connect to the API.." : "Пытаемся подключиться к API..");
            Dictionary<string, string> headers = new Dictionary<string, string> {
                {
                    "Authorization", $"Bearer {cfg._api.secretkey}"
                }
            }
            ;
            webrequest.Enqueue(api + "status", null, (code, response) => {
                Log("status code: " + code);
                Log("status response: " + response);
                if (debug) Puts("status " + code);
                if (debug) Puts("status " + response);
                if (code != 200 || response == null || response.ToString() == "Error: NameResolutionFailure") {
                    connect = false;
                    if (init) PrintError(en ? "An API connection error occurred. Contact technical support to resolve the problem" : "Произошла ошибка подключения к API. Свяжитесь с технической поддержкой для решения проблемы");
                    else DLog();
                    if (tryes == 3) {
                        PrintError(en ? "An API connection error occurred. Contact technical support to resolve the problem" : "Произошла ошибка подключения к API. Свяжитесь с технической поддержкой для решения проблемы");
                        Interface.Oxide.UnloadPlugin(Title);
                        return;
                    }
                    tryes++;
                    PrintError(en ? $"[{tryes}/3] Reconnecting in 10 sec..." : $"[{tryes}/3] Переподключаемся через 10 сек...");
                    timers = timer.Once(10f, () => {
                        TryConnectToAPI(true);
                    }
                    );
                    return;
                }
                if (timers != null) {
                    timer.Destroy(ref timers);
                    timers = null;
                }
                Connection response_deserialized = JsonConvert.DeserializeObject<Connection>(response);
                if (!response_deserialized.success) {
                    connect = false;
                    Log("status response_deserialized.success: " + response_deserialized.success);
                    if (init) PrintError(en ? "An API connection error occurred. Contact technical support to resolve the problem" : "Произошла ошибка подключения к API. Свяжитесь с технической поддержкой для решения проблемы");
                    else DLog();
                    return;
                }
                connect = true;
                if (init) PrintWarning(en ? "Successfully connected to the API" : "Успешно подключились к API. Получаем список предметов..");
                if (init) {
                    webrequest.Enqueue(api + $"items?sort=items.skin_id&filter[items.game]=rust&page[size]=1", null, (codes, responses) => {
                        Log("status + items?sort=items.skin_id&filter[items.game]=rust&page[size]=1 codes: " + codes);
                        Log("status + items?sort=items.skin_id&filter[items.game]=rust&page[size]=1 responses: " + responses);
                        if (debug) Puts("status + items?sort=items.skin_id&filter[items.game]=rust&page[size]=1 " + codes);
                        if (codes != 200) {
                            connect = false;
                            PrintError(en ? "An API connection error occurred. Contact technical support to resolve the problem" : "Произошла ошибка подключения к API. Свяжитесь с технической поддержкой для решения проблемы");
                            return;
                        }
                        BotItems response_deserializeds = JsonConvert.DeserializeObject<BotItems>(responses);
                        if (response_deserializeds == null) {
                            connect = false;
                            PrintError(en ? "An API connection error occurred. Contact technical support to resolve the problem" : "Произошла ошибка подключения к API. Свяжитесь с технической поддержкой для решения проблемы");
                            return;
                        }
                        if (init) PrintWarning(en ? $"Successfully obtained a list of items - available {response_deserializeds.count} items" : $"Успешно получили список предметов - доступно {response_deserializeds.count} предметов"
// ... [Code preview truncated due to length. Full source in attached file] ...

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