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

FREE ZStickers : 1.1.0 1.1.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using UnityEngine;
using System.Collections.Generic;
using Oxide.Core;
using System.Linq;
using Oxide.Game.Rust.Cui;
using System;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
namespace Oxide.Plugins {
    [Info("ZStickers", "JOSH-Z", "1.1.0")]
    [Description("Add collectable stickers that can be used while chatting.Stickers can be shown anywhere on your screen.")]
    class ZStickers : RustPlugin {
        // Planned:
        // - Better cleanup: remove deleted stickers from lists
        // - Add stickers from within UI
        // Researching:
        // -
        // Changelog 1.1.0:
        // - Fixed Collection next/prev buttons
        // - Added Sticker token items - unwrap for a token
        // - Added Admin chat command /sticker spawntoken|st [amount]
        // - Added Improved sticker unlock preview
        // - Added Packages to unlock multiple stickers at once (buy 5 random instead of 1)
        // - Added Buy from specific packages
        // - Added unlock package tier collection option - only unlock stickers from one group of stickers
        // - Added unlock package tier permission option - only unlock if player has permission
        // - Fixed Economics plugin usage
        // - Improved returning to browser after creating trade offer for sticker
        // - Fixed error with removed stickers in RemoveInactive
        // - Added player sticker usage cooldown
        // Changelog 1.1.1:
        // - Patch for Rust update Oct 3
#region Fields
        private static ZStickers ins;
        [PluginReference]
        private Plugin ImageLibrary, ZCoins, ServerRewards, Economics;
        const string permAdmin = "zstickers.admin";
        const string permTrade = "zstickers.trade";
        const string permStickers = "zstickers.use";
        const string permStickersTeam = "zstickers.teamchat";
        const string dataFileNameStickers = "ZStickers/stickers";
        const string dataFileNamePlayerStickers = "ZStickers/player_stickers";
        const string dataFileNameMarketData = "ZStickers/market_data";
        const string dataDirStickerPacks = "ZStickers/import";
        // no slash on end
        const ulong zcoin_skin = 2811087215;
        //const ulong sticker_token_skin = 3104407217;
        const string UIPanelName = "zstickers_panel";
        const string UIPanelChatStickers = "zstickers_chatstickers";
        const string UIPanelStickerBrowser = "zstickers_stickerbrowser";
        const string UIPanelStickerTrader = "zstickers_stickertrader";
        const string UIPanelStickerUnlock = "zstickers_stickerunlock";
        Dictionary<BasePlayer, List<string>> UIUsers = new Dictionary<BasePlayer, List<string>>();
        Dictionary<BasePlayer, PlayerSettings> playerSettings = new Dictionary<BasePlayer, PlayerSettings>();
        Dictionary<BasePlayer, float> playerNextUnlockBroadcast = new Dictionary<BasePlayer, float>();
        Dictionary<BasePlayer, float> playerCooldowns = new Dictionary<BasePlayer, float>();
        const string icon_lock = "https://i.imgur.com/kwYZWr0.png";
        const string icon_lock2 = "https://i.imgur.com/Sa8zYaj.png";
        const string icon_lock_open = "https://i.imgur.com/rbfmhiV.png";
        const string icon_edit2 = "https://i.imgur.com/hFIst03.png";
        const string icon_eye = "https://i.imgur.com/USgI4Wl.png";
        const string effect_unwrap = "assets/prefabs/misc/xmas/presents/effects/unwrap.prefab";
        public Timer stickerTimeout = null;
        public bool DATA_SAVE_REQUIED = false;
        public bool DEBUG = false;
#endregion
#region Hooks
        void Init() {
            Debug.Log($"::g:: LOADED STICKERS");
            if (!LoadConfigVariables()) {
                Debug.Log("Errors in config file, please validate the file and try again");
                return;
            }
            // make sure there's always one default unlock button
            if (configData.stickerUnlockPacks == null || configData.stickerUnlockPacks.Count == 0) {
                configData.stickerUnlockPacks.Add(new Tier());
                SaveConf();
            }
            permission.RegisterPermission(permAdmin, this);
            permission.RegisterPermission(permStickers, this);
            permission.RegisterPermission(permStickersTeam, this);
            permission.RegisterPermission(permTrade, this);
        }
        void OnServerInitialized() {
            ins = this;
            LoadUIImages();
            //RefreshAllStickerData();
            CleanupStickerTrades();
            RemoveInactive();
            UpdateStickerWeights();
            if (!configData.basicSettings.stickerTokenItemsEnabled) Unsubscribe(nameof(OnItemAction));
        }
        void Unload() {
            CloseAllUIs();
            SaveData();
        }
        void OnPlayerDisconnected(BasePlayer player, string reason) {
            if (player == null) return;
            // keep track of player last seen if player has any unlocked stickers
            if (storedPlayerStickers.unlockedStickers.ContainsKey(player.UserIDString)) storedPlayerStickers.playersLastSeen[player.UserIDString] = UnixTimeStampUTC();
        }
        void OnPlayerConnected(BasePlayer player) {
            if (player == null) return;
            // keep track of player last seen if player has any unlocked stickers
            if (storedPlayerStickers.unlockedStickers.ContainsKey(player.UserIDString)) storedPlayerStickers.playersLastSeen[player.UserIDString] = UnixTimeStampUTC();
        }
        object OnPlayerChat(BasePlayer player, string message, ConVar.Chat.ChatChannel channel) {
            if (!permission.UserHasPermission(player.UserIDString, permAdmin) && !permission.UserHasPermission(player.UserIDString, permStickers)) return null;
            if (channel == ConVar.Chat.ChatChannel.Cards) return null;
            if (channel != ConVar.Chat.ChatChannel.Global && !permission.UserHasPermission(player.UserIDString, permStickersTeam)) return null;
            var first = message.IndexOf(":");
            var last = message.LastIndexOf(":");
            if (first != -1 && last != -1 && first != last) {
                if (!CanSendSticker(player)) return null;
                int ssF = message.IndexOf(":");
                int ssT = message.LastIndexOf(":") + 1;
                var tag = message.Substring(ssF, ssT - ssF);
                if (storedStickers.stickers.ContainsKey(tag)) {
                    List<string> playerStickers;
                    if (!storedPlayerStickers.unlockedStickers.TryGetValue(player.UserIDString, out playerStickers)) return null;
                    if (playerStickers.Contains(tag)) ShowSticker(tag);
                    return null;
                }
            }
            return null;
        }
        bool CanSendSticker(BasePlayer player) {
            if (configData.basicSettings.showStickerCooldown <= 0) return true;
            float playerCooldown;
            if (playerCooldowns.TryGetValue(player, out playerCooldown)) {
                var timeleft = Math.Ceiling(playerCooldown - Time.realtimeSinceStartup);
                if(timeleft > 0) {
                    player.ChatMessage($"Please wait {Math.Ceiling(timeleft)} seconds before sending another sticker");
                    return false;
                }
            }
            playerCooldowns[player] = Time.realtimeSinceStartup + configData.basicSettings.showStickerCooldown;
            return true;
        }
        object OnItemAction(Item item, string action, BasePlayer player) {
            if (configData.basicSettings.stickerTokenItemsEnabled && item.skin == configData.basicSettings.stickerTokenItemSkinID && action == "open" && item.info.shortname == "wrappedgift") {
                var amount = item.amount;
                item.Remove();
                Effect effect = new Effect(effect_unwrap, player.transform.position, Vector3.zero);
                if (effect != null) EffectNetwork.Send(effect);
                AddPlayerTokens(player, amount);
            }
            return null;
        }
#endregion
#region ImageLibrary
        private void LoadUIImages() {
            if (ImageLibrary == null) {
                Debug.LogError("ImageLibray not found!");
                return;
            }
            Dictionary<string, string> newLoadOrder = new Dictionary<string, string>();
            newLoadOrder.Add("icon_lock_url", icon_lock);
            newLoadOrder.Add("icon_lock_url2", icon_lock2);
            newLoadOrder.Add("icon_lock_open_url", icon_lock_open);
            newLoadOrder.Add(configData.currencySettings.icon_currency, configData.currencySettings.icon_currency);
            newLoadOrder.Add("icon_edit_url2", icon_edit2);
            newLoadOrder.Add("icon_eye_url", icon_eye);
            foreach (var img in storedStickers.stickers) newLoadOrder.Add(img.Key, img.Value.DUI_URL);
            if (newLoadOrder.Count > 0) ImageLibrary.Call("ImportImageList", Title, newLoadOrder);
        }
        private void AddImage(string name, string url) {
            if (!(bool)ImageLibrary.Call("HasImage", name)) {
                ImageLibrary.Call("AddImage", url, name);
            }
        }
        private string GetImage(string filename, ulong skinID = 0UL) {
            return ImageLibrary?.Call<string>("GetImage", filename, skinID, false);
        }
#endregion
#region Stickers
        void ShowStickerBadge(string stickerTag, BasePlayer player, string message) {
            var stickerData = GetStickerData(stickerTag);
            if (stickerData == null || stickerData.DUI_URL == "") return;
            var pad = 5f;
            var imgWH = 50f;
            var imgW = stickerData.DUI_HEIGHT > stickerData.DUI_WIDTH ? (stickerData.DUI_WIDTH / stickerData.DUI_HEIGHT) * imgWH : imgWH;
            var imgH = stickerData.DUI_WIDTH > stickerData.DUI_HEIGHT ? (stickerData.DUI_HEIGHT / stickerData.DUI_WIDTH) * imgWH : imgWH;
            var newPlayerUI = new CuiElementContainer();
            newPlayerUI.Add(CreateUIPanel($"0 1", $"0 1", HexToRGBA(color_dark, 0.7f), false, $"30 -120", $"270 -60"), "Overlay", UIPanelName);
            newPlayerUI.Add(CreateUIPanel("0 0", "0 1", "0 0 0 0", false, $"{pad} {pad}", $"{pad + imgWH} -10"), UIPanelName, "badge_panel_img");
            newPlayerUI.Add(CreateNewLabel(message, $"0 0", $"1 1", TextAnchor.MiddleCenter, 12, "1 1 1 1", $"{pad + pad + imgWH} {pad}", $"{-pad} {-pad}", CuiFont.ROBOTO_REGULAR), UIPanelName);
            newPlayerUI.Add(new CuiElement {
                Name = CuiHelper.GetGuid(), Parent = "badge_panel_img", Components = {
                    new CuiRawImageComponent {
                        Png = ImageLibrary.Call<string>("GetImage", stickerTag)
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"{-imgW / 2} {-imgH / 2}", OffsetMax = $"{imgW / 2} {imgH / 2}"
                    }
                }
            }
            );
            ResetStickerTimeout();
            List<BasePlayer> trgs = new List<BasePlayer>(BasePlayer.activePlayerList.ToList());
            if (trgs != null) {
                foreach (var target in trgs) {
                    if (target != null && target.IsConnected && !storedPlayerStickers.playerHideStickers.Contains(target.UserIDString)) AddUI(target, newPlayerUI, UIPanelName);
                }
            }
        }
        bool AddSticker(string tag, StickerData stickerData, bool hidden = false) {
            if (storedStickers.stickers.ContainsKey(tag)) return false;
            if (hidden) stickerData.TIER = "hidden";
            storedStickers.stickers.Add(tag, stickerData);
            AddImage(tag, stickerData.DUI_URL);
            return true;
        }
        void ShowSticker(string stickerTag, StickerData presetPreset = null) {
            var preset = presetPreset ?? GetStickerData(stickerTag);
            if (preset == null || preset.DUI_URL == "") {
                Debug.Log($"::r:: sticker {stickerTag} not found");
                return;
            }
            var newPlayerUI = new CuiElementContainer();
            float pHor, pVer, oHorMin, oHorMax, oVerMin, oVerMax;
            GetUIPosition(preset, out pHor, out pVer, out oHorMin, out oHorMax, out oVerMin, out oVerMax);
            CuiPanel newPanel = CreateUIPanel($"{pHor} {pVer}", $"{pHor} {pVer}", "0 0 0 0", false, $"{oHorMin} {oVerMin}", $"{oHorMax} {oVerMax}");
            newPlayerUI.Add(newPanel, "Overlay", UIPanelName);
            newPlayerUI.Add(new CuiElement {
                Name = CuiHelper.GetGuid(), Parent = UIPanelName, Components = {
                    new CuiRawImageComponent {
                        Png = ImageLibrary.Call<string>("GetImage", stickerTag)
                    }
                    , new CuiRectTransformComponent {
                        AnchorMin = "0 0", AnchorMax = "1 1"
                    }
                }
            }
            );
            ResetStickerTimeout();
            List<BasePlayer> trgs = new List<BasePlayer>(BasePlayer.activePlayerList.ToList());
            if (trgs != null) {
                foreach (var target in trgs) {
                    if (target != null && target.IsConnected && !storedPlayerStickers.playerHideStickers.Contains(target.UserIDString)) AddUI(target, newPlayerUI, UIPanelName);
                }
            }
        }
        StickerData GetStickerData(string sticker) {
            StickerData preset;
            if (!storedStickers.stickers.TryGetValue(sticker, out preset)) return null;
            return preset;
        }
        void ResetStickerTimeout() {
            if (stickerTimeout != null) {
                stickerTimeout.Destroy();
                stickerTimeout = null;
            }
            stickerTimeout = timer.Once(configData.basicSettings.stickerDisplayTime, () => {
                CloseAllUIs(UIPanelName);
            }
            );
        }
        Dictionary<StickerPair, int> AVAILABLE_STICKERS_WEIGHTED = new Dictionary<StickerPair, int>();
        class StickerPair {
            public string name;
            public StickerData stickerData;
        }
        Dictionary<StickerPair, int> GetAvailableStickers(bool forceUpdate = false) {
            if (AVAILABLE_STICKERS_WEIGHTED.Count == 0 || forceUpdate) {
                Dictionary<StickerPair, int> newStickers = new Dictionary<StickerPair, int>();
                foreach (var sticker in new Dictionary<string, StickerData>(storedStickers.stickers)) {
                    if (sticker.Value.TIER == "hidden") continue;
                    // skip if sticker is already in newStickers
                    if (newStickers.Any(x => x.Key.name == sticker.Key)) continue;
                    // no more max owners 0 allowed
                    if (sticker.Value.MAX_OWNERS <= 0) continue;
                    if (sticker.Value.CURRENT_OWNERS >= sticker.Value.MAX_OWNERS) continue;
                    var sticker_weight = 0;
                    sticker_weight = sticker.Value.MAX_OWNERS - sticker.Value.CURRENT_OWNERS;
                    newStickers.Add(new StickerPair() {
                        name = sticker.Key, stickerData = sticker.Value
                    }
                    , sticker_weight);
                }
                AVAILABLE_STICKERS_WEIGHTED = newStickers;
            }
            return AVAILABLE_STICKERS_WEIGHTED;
        }
        void ImportStickerPack(string filename, bool hidden = false) {
            if (!Interface.Oxide.DataFileSystem.ExistsDatafile($"{dataDirStickerPacks}/{filename}")) {
                Debug.Log($"Sticker pack {filename} not found");
                return;
            }
            var stickerPack = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, StickerData>>($"{dataDirStickerPacks}/{filename}");
            if (stickerPack == null) {
                Debug.Log($"Corrupt JSON in sticker pack");
                return;
            }
            if (stickerPack.Count == 0) {
                Debug.Log($"Corrupt JSON in sticker pack");
                return;
            }
            Debug.Log($"Adding sticker pack '{filename}' with {stickerPack.Count} stickers...");
            List<string> added = new List<string>();
            List<string> failed = new List<string>();
            foreach (var sticker in new Dictionary<string, StickerData>(stickerPack)) {
                if (AddSticker(sticker.Key, sticker.Value, hidden)) {
                    added.Add(sticker.Key);
                }
                else {
                    failed.Add(sticker.Key);
                }
            }
            Debug.Log($"Finished adding sticker pack '{filename}'.{added.Count} stickers added, {failed.Count} stickers already existed.\n" + $"Added:\n {(string.Join(" ", added))}\n" + $"Failed:\n {(string.Join(" ", failed))}");
        }
#endregion
#region Tokens
        private int AddPlayerTokens(BasePlayer player, int amount, bool amountIsMax = false) {
            if (!storedPlayerStickers.unlockTokens.ContainsKey(player.UserIDString)) storedPlayerStickers.unlockTokens.Add(player.UserIDString, 0);
            if (amountIsMax) {
                var balance = storedPlayerStickers.unlockTokens[player.UserIDString];
                if (balance < amount) {
                    var tokens = amount - balance;
                    storedPlayerStickers.unlockTokens[player.UserIDString] = amount;
                    Debug.Log($"AddPlayerTokens {player.displayName}, amount: {tokens}, new balance: {storedPlayerStickers.unlockTokens[player.UserIDString]}");
                    player.ChatMessage($"<color={colorGreen}>You received <color={colorRed}>{tokens}</color> sticker token{(tokens > 1 ? "s" : "")}</color>");
                }
            }
            else {
                storedPlayerStickers.unlockTokens[player.UserIDString] += amount;
                Debug.Log($"AddPlayerTokens {player.displayName}, amount: {amount}, new balance: {storedPlayerStickers.unlockTokens[player.UserIDString]}");
                player.ChatMessage($"<color={colorGreen}>You received <color={colorRed}>{amount}</color> sticker token{(amount > 1 ? "s" : "")}</color>");
            }
            return storedPlayerStickers.unlockTokens[player.UserIDString];
        }
#endregion
#region Unlock Stickers
        private bool UnlockPlayerSticker(BasePlayer player, string inputTier) {
            if (inputTier == "") return false;
            Tier tier = configData.stickerUnlockPacks.FirstOrDefault(x => x.name == inputTier);
            if (tier == null) return false;
            if (!storedPlayerStickers.unlockedStickers.ContainsKey(player.UserIDString)) storedPlayerStickers.unlockedStickers.Add(player.UserIDString, new List<string>());
            var playerTokens = GetPlayerTokens(player);
            if (playerTokens < tier.price) {
                player.ChatMessage($"You don't have enough sticker tokens.You have {playerTokens}, required: {tier.price}");
                return false;
            }
            var pSet = GetPlayerSettings(player);
            if (pSet == null) return false;
            string unlockedString = "";
            // HERE WE FIND OUT WHAT STICKERS ARE AVAILABLE AND WE PICK A RANDOM WEIGHTED STICKER
            List<string> unlockedStickers;
            if (!GetRandomStickersForPlayer(player, tier.name, out unlockedStickers) || unlockedStickers.Count != tier.amount) {
                player.ChatMessage($"No stickers available to unlock");
                return false;
            }
            pSet.justUnlockedStickers.Clear();
            foreach (var unlockedSticker in unlockedStickers) {
                storedPlayerStickers.unlockedStickers[player.UserIDString].Add(unlockedSticker);
                storedStickers.stickers[unlockedSticker].CURRENT_OWNERS++;
                Debug.Log($"{player.displayName} unlocked {tier.name} sticker {unlockedSticker}");
                pSet.justUnlockedStickers.Add(unlockedSticker);
            }
            storedPlayerStickers.unlockTokens[player.UserIDString] -= tier.price;
            unlockedString = string.Join(",", unlockedStickers);
            if (configData.basicSettings.showUnlockNotification) {
                var message = $"<size=15><color={colorYellow}>{unlockedStickers.First()}</color></size>\nSticker unlocked by\n{player.displayName}";
                ShowStickerBadge(unlockedStickers.First(), player, message);
            }
            storedPlayerStickers.playersLastSeen[player.UserIDString] = UnixTimeStampUTC();
            if (!playerNextUnlockBroadcast.ContainsKey(player)) playerNextUnlockBroadcast.Add(player, 0);
            if (playerNextUnlockBroadcast[player] < Time.realtimeSinceStartup) {
                playerNextUnlockBroadcast[player] = Time.realtimeSinceStartup + 7f;
                PrintToChat($"<size=11><color={GetTierColor(tier.name, 1, true)}><color={GetTierColor(tier.name, 0.5f, true)}>{player.displayName}</color> unlocked a new sticker in the <color=#ffffff>/sticker</color> menu</color></size>");
            }
            player.ChatMessage($"You unlocked sticker(s) {unlockedString}");
            UpdateStickerBrowser(player);
            DATA_SAVE_REQUIED = true;
            return true;
        }
        bool GetRandomStickersForPlayer(BasePlayer player, string inputTier, out List<string> stickernames) {
            //var possibleStickers = new Dictionary<string, StickerData>();
            stickernames = new List<string>();
            if (inputTier == "") return false;
            Tier tier = configData.stickerUnlockPacks.FirstOrDefault(x => x.name == inputTier);
            if (tier == null) return false;
            if (tier.permission != "" && !HasPermission(player.UserIDString, tier.permission)) return false;
            List<string> playerStickers;
            if (!storedPlayerStickers.unlockedStickers.TryGetValue(player.UserIDString, out playerStickers)) return false;
            var amount = tier.amount;
            var availableStickers = new Dictionary<StickerPair, int>(GetAvailableStickers());
            if (availableStickers.Count == 0) {
                player.ChatMessage($"No stickers available to unlock");
                return false;
            }
            if(DEBUG) Debug.Log($"::p:: {availableStickers.Count} available stickers for player {player.displayName}:\n::p:: {string.Join(", ", availableStickers.Keys.ToList())}");
            var totalWeight = availableStickers.Values.Sum();
            for(var i = 0; i < amount; i++) {
                var weightLeft = UnityEngine.Random.Range(0, totalWeight - 1);
                if (DEBUG) Debug.Log($"::o:: Total weight all stickers: {totalWeight} - Weight left: {weightLeft}");
                foreach (var sticker in new Dictionary<StickerPair, int>(availableStickers)) {
                    if (tier.collection != "" && sticker.Key.stickerData.COLLECTION != tier.collection) continue;
                    weightLeft -= sticker.Value;
                    if (DEBUG) Debug.Log($"::o:: Sticker {sticker.Key} weight: {sticker.Value} - Weight left: {weightLeft}");
                    if (weightLeft <= 0) {
                        stickernames.Add(sticker.Key.name);
                        if (DEBUG) Debug.Log($"::g:: Weight left <= 0, picked sticker {sticker.Key} to unlock");
                        break;
                    }
                }
            }
            return stickernames.Count == amount;
        }
        //bool GetRandomStickerForPlayer(BasePlayer player, string inputTier, out string stickername)
        //{
        //    //var possibleStickers = new Dictionary<string, StickerData>();
        //    stickername = "";
        //    if (inputTier == "")
        //        return false;
        //    Tier tier = configData.stickerUnlockPacks.FirstOrDefault(x => x.name == inputTier);
        //    if (tier == null)
        //        return false;
        //    List<string> playerStickers;
        //    if (!storedPlayerStickers.unlockedStickers.TryGetValue(player.UserIDString, out playerStickers))
        //        return false;
        //    #region old
        //    // //int totalStickers = 0;
        //    // int totalWeight = 0;
        //    //// foreach (var sticker in new Dictionary<string, StickerData>(storedStickers.stickers))
        //    // foreach (var sticker in available)
        //    // {
        //    //     if (sticker.Value.TIER == "hidden")
        //    //         continue;
        //    //     //totalStickers++;
        //    //     //if (possibleStickers.ContainsKey(sticker.Key) || playerStickers.Contains(sticker.Key))
        //    //     //    continue;
        //    //     // we no longer check if the player already owns the sticker
        //    //     if (possibleStickers.ContainsKey(sticker.Key))
        //    //         continue;
        //    //     // will be removed later when tiers get removed
        //    //     if (tier.name != "" && tier.name != "random" && sticker.Value.TIER != tier.name)
        //    //         continue;
        //    //     if (sticker.Value.MAX_OWNERS > 0 && sticker.Value.CURRENT_OWNERS >= sticker.Value.MAX_OWNERS)
        //    //         continue;
        //    //     if (sticker.Value.MAX_OWNERS > 0)
        //    //         totalWeight += sticker.Value.MAX_OWNERS - sticker.Value.CURRENT_OWNERS;
        //    //     possibleStickers.Add(sticker.Key, sticker.Value);
        //    // }
        //    #endregion
        //    var availableStickers = new Dictionary<string, int>(GetAvailableStickers());
        //    var totalWeight = availableStickers.Values.Sum();
        //    var weightLeft = UnityEngine.Random.Range(0, totalWeight - 1);
        //    if (DEBUG)
        //    {
        //        Debug.Log($"::p:: {availableStickers.Count} available stickers for player {player.displayName}:\n::p:: {string.Join(", ", availableStickers.Keys.ToList())}");
        //        Debug.Log($"::o:: Total weight all stickers: {totalWeight} - Weight left: {weightLeft}");
        //    }
        //    if (availableStickers.Count == 0)
        //    {
        //        player.ChatMessage($"No stickers available to unlock");
        //        return false;
        //    }
        //    //foreach (var sticker in new Dictionary<string, StickerData>(possibleStickers))
        //    foreach (var sticker in new Dictionary<string, int>(availableStickers))
        //    {
        //        //var posMaxWeight = sticker.Value.MAX_OWNERS - sticker.Value.CURRENT_OWNERS;
        //        weightLeft -= sticker.Value;
        //        if (DEBUG)
        //            Debug.Log($"::o:: Sticker {sticker.Key} weight: {sticker.Value} - Weight left: {weightLeft}");
        //        if (weightLeft <= 0)
        //        {
        //            stickername = sticker.Key;
        //            if (DEBUG)
        //                Debug.Log($"::g:: Weight left <= 0, picked sticker {sticker.Key} to unlock");
        //            break;
        //        }
        //    }
        //    return true;
        //}
        void AdminLockSticker(BasePlayer player, string sticker) {
            if (!storedPlayerStickers.unlockedStickers.ContainsKey(player.UserIDString)) return;
            List<string> playerStickers;
            if (!storedPlayerStickers.unlockedStickers.TryGetValue(player.UserIDString, out playerStickers)) return;
            if (!playerStickers.Contains(sticker)) return;
            playerStickers.Remove(sticker);
            storedStickers.stickers[sticker].CURRENT_OWNERS--;
            player.ChatMessage($"You locked sticker {sticker}");
        }
        void AdminUnlockSticker(BasePlayer player, string sticker) {
            if (!storedStickers.stickers.ContainsKey(sticker)) return;
            if (!storedPlayerStickers.unlockedStickers.ContainsKey(player.UserIDString)) storedPlayerStickers.unlockedStickers.Add(player.UserIDString, new List<string>());
            List<string> playerStickers;
            if (!storedPlayerStickers.unlockedStickers.TryGetValue(player.UserIDString, out playerStickers)) return;
            playerStickers.Add(sticker);
            storedStickers.stickers[sticker].CURRENT_OWNERS++;
            player.ChatMessage($"You unlocked sticker {sticker}");
        }
#endregion
#region Sticker Trader
        private bool CreateStickerOffer(BasePlayer player, string stickerToSell) {
            List<string> playerStickers;
            if (!storedPlayerStickers.unlockedStickers.TryGetValue(player.UserIDString, out playerStickers)) return false;
            if (!PlayerOwnsSticker(player, stickerToSell, true)) return false;
            var pSet = GetPlayerSettings(player);
            if (pSet == null) return false;
            var stickerInfo = GetStickerData(stickerToSell);
            if (stickerInfo == null) return false;
            if (storedMarketData.stickerTrades.Any(x => x.sellerID == player.UserIDString && x.sticker == stickerToSell)) {
                player.ChatMessage($"You already placed this sticker on the market");
                return false;
            }
            var tradeOffer = new StickerTrade() {
                sellerID = player.UserIDString, sellerName = player.displayName, created = DateTimeOffset.Now.ToUnixTimeSeconds(), price = pSet.inputTradeAmount, sticker = stickerToSell, tier = stickerInfo.TIER
            }
            ;
            storedMarketData.stickerTrades.Add(tradeOffer);
            var message = $"{player.displayName} is selling\n" + $"<size=15><color={colorYellow}>{stickerToSell}</color></size>\n" + $"for {pSet.inputTradeAmount} {configData.currencySettings.currencyName}";
            if (configData.basicSettings.showUnlockNotification) ShowStickerBadge(stickerToSell, player, message);
            PrintToChat($"<size=12><color={colorYellow}><color={colorOrange}>{player.displayName}</color> is selling sticker <color={colorRed}>{stickerToSell}</color> on the <color={colorOrange}>/sticker</color> market for <color={colorRed}>{pSet.inputTradeAmount}</color> {configData.currencySettings.currencyName}</color></size>");
            player.ChatMessage($"You successfully placed sticker {stickerToSell} on the market for {pSet.inputTradeAmount} {configData.currencySettings.currencyName}");
            pSet.detailsSticker = "";
            pSet.tab = "browser";
            //pSet.itemListPage = 0;
            SaveData();
            UpdateStickerBrowser(player);
            return true;
        }
        void RemoveStickerOffer(BasePlayer player, string stickerToRemove) {
            if (!PlayerOwnsSticker(player, stickerToRemove, true)) return;
            storedMarketData.stickerTrades.RemoveAll(x => x.sellerID == player.UserIDString && x.sticker == stickerToRemove);
            var pSet = GetPlayerSettings(player);
            if (pSet != null) pSet.detailsSticker = "";
            SaveData();
            UpdateStickerBrowser(player);
            player.ChatMessage($"You cancelled your trade offer, sticker is safu");
        }
        void BuyStickerTrade(BasePlayer player, string[] args) {
            var pSet = GetPlayerSettings(player);
            var ownerID = args[1];
            var stickerName = args[2];
            var trade = storedMarketData.stickerTrades.FirstOrDefault(x => x.sellerID == ownerID && x.sticker == stickerName);
            if (trade == null) {
                Debug.Log($"::r:: trade is null - {player.displayName} {player.UserIDString} - ownerID {ownerID} - sticker {stickerName}");
                return;
            }
            if (trade.isSold) {
                Debug.Log($"::r:: trade.isSold - {player.displayName} {player.UserIDString} - ownerID {ownerID} - sticker {stickerName}");
                return;
            }
            // check ownership seller
            var sellerUnlocked = GetUnlockedStickers(ownerID);
            if (!sellerUnlocked.Contains(stickerName)) {
                player.ChatMessage($"Something went wrong");
                return;
            }
            var possibleSeller = FindPlayerByName(trade.sellerID);
            var currency = GetCurrency();
            // when using items as currency, the seller has to be connected in order to do a trade
            if (currency == StickerCurrency.Item) {
                if (possibleSeller == null || !possibleSeller.IsConnected) {
                    player.ChatMessage($"Can't trade sticker: The seller ({trade.sellerName}) is not online.");
                    return;
                }
                // check free slots
                if ((possibleSeller.inventory.containerMain.capacity - possibleSeller.inventory.containerMain.itemList.Count) + (possibleSeller.inventory.containerBelt.capacity - possibleSeller.inventory.containerBelt.itemList.Count) < 1) {
                    player.ChatMessage($"Can't trade sticker: The seller ({trade.sellerName}) does not have enough inventory space.");
                    return;
                }
            }
            // check and take buyer currency
            if (PlayerCurrencyAmount(player) < trade.price || !TryTakeCurrency(player, trade.price)) {
                player.ChatMessage($"You can't afford this!");
                UpdateStickerBrowser(player);
                return;
            }
            // try changing ownership
            if (!TradeStickerOwnership(trade.sellerID, player.UserIDString, stickerName)) {
                player.ChatMessage($"You can't afford this!");
                Debug.Log($"::r::TradeStickerOwnership false - {player.displayName} {player.UserIDString} - ownerID {ownerID} - sticker {stickerName}");
                UpdateStickerBrowser(player);
                return;
            }
            // SOLD!
            trade.isSold = true;
            trade.buyerID = player.UserIDString;
            player.ChatMessage($"You successfully bought {trade.sellerName}'s sticker {stickerName} for {trade.price} {configData.currencySettings.currencyName}");
            if (!TryGiveCurrency(ulong.Parse(trade.sellerID), trade.price)) {
                player.ChatMessage($"Something went terribly wrong while selling your sticker.Your sticker and your money is gone, contact an admin");
                Debug.Log($"::r:: Something went terribly wrong while selling your sticker.Your sticker and your money is gone, contact an admin - {player.displayName} {player.UserIDString} - ownerID {ownerID} - sticker {stickerName}");
                if (possibleSeller != null) possibleSeller.ChatMessage($"Something went terribly wrong while selling your sticker.Your sticker and your money is gone, contact an admin");
            }
            else {
                Debug.Log($"::g:: Transfering {trade.price} {configData.currencySettings.currencyName} from {player.displayName} to {trade.sellerName} for selling sticker {stickerName}");
                if (possibleSeller != null) possibleSeller.ChatMessage($"{player.displayName} bought your sticker {stickerName} for {trade.price} {configData.currencySettings.currencyName}");
            }
            storedMarketData.stickerTrades.RemoveAll(x => x.sellerID == ownerID && x.sticker == stickerName);
            SaveData();
            if (pSet != null) {
                pSet.tab = "stickertrader";
                pSet.detailsSticker = "";
                pSet.detailsStickerOwnerID = "";
            }
            UpdateStickerBrowser(player);
        }
        bool TradeStickerOwnership(string seller, string buyer, string stickerName) {
            List<string> sellerStickers;
            if (!storedPlayerStickers.unlockedStickers.TryGetValue(seller, out sellerStickers) || !sellerStickers.Contains(stickerName)) return false;
            if (!storedPlayerStickers.unlockedStickers.ContainsKey(buyer)) storedPlayerStickers.unlockedStickers.Add(buyer, new List<string>());
            List<string> buyerStickers;
            //if (!storedPlayerStickers.unlockedStickers.TryGetValue(buyer, out buyerStickers) || buyerStickers.Contains(stickerName))
            if (!storedPlayerStickers.unlockedStickers.TryGetValue(buyer, out buyerStickers)) return false;
            sellerStickers.Remove(stickerName);
            // should remove only one
            buyerStickers.Add(stickerName);
            return true;
        }
#endregion
#region Currency / Payment
        enum StickerCurrency {
            Item, ZCoins, ServerRewards, Economics
        }
        StickerCurrency GetCurrency() {
            switch (configData.currencySettings.currency) {
                case 0 : return StickerCurrency.Item;
                case 1 : return StickerCurrency.ZCoins;
                case 2 : return StickerCurrency.ServerRewards;
                case 3 : return StickerCurrency.Economics;
            }
            return StickerCurrency.Item;
        }
        bool TryTakeCurrency(BasePlayer player, int amount) {
            var currency = GetCurrency();
            switch (currency) {
                case StickerCurrency.Item : if (TryTakeItems(player, amount)) return true;
                break;
                case StickerCurrency.ZCoins : if (ZCoins == null) return false;
                if (ZCoins.Call<bool>("TakeCoins", player, amount, true)) return true;
                break;
                case StickerCurrency.ServerRewards : if (ServerRewards == null) return false;
                if (ServerRewards.Call<bool>("TakePoints", player.userID, amount)) return true;
                break;
                case StickerCurrency.Economics : if (Economics == null) return false;
                if (Economics.Call<bool>("Withdraw", player.userID, (double)amount)) return true;
                break;
                default : return false;
            }
            return false;
        }
        bool TryTakeItems(BasePlayer player, int amount) {
            var items = Facepunch.Pool.GetList<Item>();
            items.AddRange(player.inventory.containerMain.itemList.Where(x => x.info.shortname == configData.currencySettings.currencyItemName && x.skin == configData.currencySettings.currencySkinID));
            items.AddRange(player.inventory.containerBelt.itemList.Where(x => x.info.shortname == configData.currencySettings.currencyItemName && x.skin == configData.currencySettings.currencySkinID));
            var itemAmount = items.Sum(x => x.amount);
            if (itemAmount < amount) return false;
            var amountLeft = amount;
            foreach (var item in items) {
                if (amountLeft >= item.amount) {
                    amountLeft -= item.amount;
                    item.Remove();
                }
                else {
                    item.amount -= amountLeft;
                    item.MarkDirty();
                    amountLeft = 0;
                }
                if (amountLeft <= 0) break;
            }
            return amountLeft <= 0;
        }
        bool TryGiveCurrency(ulong playerID, int amount) {
            var currency = GetCurrency();
            switch (currency) {
                case StickerCurrency.Item : BasePlayer player = FindPlayerByName(playerID.ToString());
                var item = ItemManager.CreateByName(configData.currencySettings.currencyItemName, amount, configData.currencySettings.currencySkinID);
                if (player == null || item == null) return false;
                if (!item.MoveToContainer(player.inventory.containerMain, -1, true, true) && item.MoveToContainer(player.inventory.containerBelt, -1, true, true)) item.Drop(player.inventory.containerMain.dropPosition, Vector3.zero, new Quaternion());
                break;
                case StickerCurrency.ZCoins : if (ZCoins == null || !ZCoins.Call<bool>("GiveOrScheduleCoins", playerID, amount)) return false;
                break;
                case StickerCurrency.ServerRewards : if (ServerRewards == null || !ServerRewards.Call<bool>("AddPoints", playerID, amount)) return false;
                break;
                case StickerCurrency.Economics : if (Economics == null || !Economics.Call<bool>("Deposit", playerID, amount)) return false;
                break;
                default : return false;
            }
            return true;
        }
        int PlayerCurrencyAmount(BasePlayer player) {
            var currency = GetCurrency();
            int amount = 0;
            switch (currency) {
                case StickerCurrency.Item : foreach (var pc in player.inventory.containerMain.itemList.FindAll(x => x.skin == configData.currencySettings.currencySkinID && x.info.shortname == configData.currencySettings.currencyItemName).ToList()) amount += pc.amount;
                foreach (var pc in player.inventory.containerBelt.itemList.FindAll(x => x.skin == configData.currencySettings.currencySkinID && x.info.shortname == configData.currencySettings.currencyItemName).ToList()) amount += pc.amount;
                break;
                case StickerCurrency.ZCoins : foreach (var pc in player.inventory.containerMain.itemList.FindAll(x => x.skin == zcoin_skin).ToList()) amount += pc.amount;
                foreach (var pc in player.inventory.containerBelt.itemList.FindAll(x => x.skin == zcoin_skin).ToList()) amount += pc.amount;
                break;
                case StickerCurrency.ServerRewards : if (ServerRewards == null) return 0;
                var obj = ServerRewards?.Call("CheckPoints", player.userID);
                if (obj == null) return 0;
                amount = (int)obj;
                break;
                case StickerCurrency.Economics : if (Economics == null) return 0;
                var ecBalance = (double)Economics?.Call("Balance", player.userID);
                amount = Convert.ToInt32(Math.Round(ecBalance));
                break;
            }
            return amount;
        }
#endregion
#region Sticker tokens
        private int GetPlayerTokens(BasePlayer player) {
            int tokens;
            if (storedPlayerStickers.unlockTokens.TryGetValue(player.UserIDString, out tokens)) return tokens;
            storedPlayerStickers.unlockTokens.Add(player.UserIDString, 0);
            return 0;
        }
        class TokenPack {
            public string name = "";
            public int price = 0;
            public int tokenAmount = 0;
        }
#endregion
#region Commands
        [ConsoleCommand("sticker")]
        private void consoleSticker(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (!arg.IsRcon && (player == null || !HasPermission(player.UserIDString, permAdmin))) {
                arg.ReplyWith("No permission");
                return;
            }
            if(arg.Args == null || arg.Args.Length == 0) {
                arg.ReplyWith("Invalid parameters");
                return;
            }
            var args = arg.Args;
            int amount;
            BasePlayer targetPlayer;
            switch(arg.Args[0]) {
                case "givetokens" : if (arg.Args.Length < 3) {
                    arg.ReplyWith($"Usage: sticker givetokens <player> <amount>");
                    return;
                }
                targetPlayer = FindPlayerByName(args[1]);
                if (targetPlayer == null) {
                    arg.ReplyWith($"Player not found");
                    return;
                }
                if (!int.TryParse(args[2], out amount) || amount <= 0) {
                    arg.ReplyWith($"Invalid amount");
                    return;
                }
                AddPlayerTokens(targetPlayer, amount);
                arg.ReplyWith($"{amount} sticker tokens given to {targetPlayer.displayName}");
                break;
                case "unlock" : if (args.Length < 3) {
                    arg.ReplyWith($"Usage: sticker unlock <player> :sticker:");
                    return;
                }
                targetPlayer = FindPlayerByName(args[1]);
                if (targetPlayer == null) {
                    arg.ReplyWith($"Player not found");
                    return;
                }
                if (!storedStickers.stickers.ContainsKey(args[2])) {
                    arg.ReplyWith($"Sticker {args[2]} not found");
                    return;
                }
                AdminUnlockSticker(targetPlayer, args[2]);
                arg.ReplyWith($"Unlocked sticker {args[2]} for {targetPlayer.displayName}");
                break;
                case "import" : if (args.Length < 2) {
                    arg.ReplyWith($"Usage: sticker import <pack file name> [hidden]");
                    return;
                }
                ImportStickerPack(args[1], args.Length > 2 && args[2] == "hidden");
                arg.ReplyWith($"Trying to add sticker pack {args[1]}, see RCON for results");
                break;
            }
        }
        [ConsoleCommand("cmdsticker")]
        private void ccmdsticker(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            var args = arg.Args;
            if (args.Length > 0) {
                switch (args[0]) {
                    case "buytokens" : TokenPack tokenPack = configData.currencySettings.tokenPacks.FirstOrDefault(x => x.name == args[1]);
                    if (tokenPack == null) return;
                    if (PlayerCurrencyAmount(player) < tokenPack.price || !TryTakeCurrency(player, tokenPack.price)) {
                        UpdateStickerBrowser(player);
                        player.ChatMessage($"You can't afford this!");
                        return;
                    }
                    else {
                        AddPlayerTokens(player, tokenPack.tokenAmount);
                        UpdateStickerBrowser(player);
                    }
                    break;
                    case "unlocksticker" : if (args.Length > 1) UnlockPlayerSticker(player, args[1]);
                    break;
                    case "sellsticker" : if (args.Length > 1) CreateStickerOffer(player, args[1]);
                    break;
                    case "cancelsell" : if (args.Length > 1) RemoveStickerOffer(player, args[1]);
                    break;
                    case "buytrade" : if (args.Length > 2) BuyStickerTrade(player, args);
                    break;
                    case "recyclestickers" : if (args.Length > 1) RecycleStickers(player, args);
                    UpdateStickerBrowser(player);
                    break;
                    case "clearsales" : storedMarketData.stickerTrades.Clear();
                    SaveData();
                    player.ChatMessage("sales cleared");
                    break;
                    case "pset" : HandlePlayerSettings(player, args);
                    break;
                    case "close" : case "exit" : CloseUI(player, UIPanelStickerBrowser);
                    CloseUI(player, UIPanelStickerUnlock);
                    break;
                }
            }
        }
        void HandlePlayerSettings(BasePlayer player, s
// ... [Code preview truncated due to length. Full source in attached file] ...

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