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

FREE TradeUI : 1.8.0 1.8.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
 * https://github.com/DocValerian/rust-plugins
 * Copyright (C) 2022 DocValerian
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.* 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
 * GNU General Public License for more details.* 
 * You should have received a copy of the GNU General Public License
 * along with this program.If not, see <http://www.gnu.org/licenses/>.* 
 * Questions and Support can be found in our Discord: https://discord.gg/8tkBFRjg3W
 * 
 */

using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Linq;
using System;
using Oxide.Game.Rust.Cui;
using System.Globalization;
using Network;
using ProtoBuf;
using System.Text.RegularExpressions;
using Newtonsoft.Json;

namespace Oxide.Plugins
{
    [Info("TradeUI", "DocValerian", "1.8.0")]
    class TradeUI : RustPlugin
    {
        static TradeUI Plugin;

        const string permUse = "tradeui.use";
        bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);

        #region ConfigDataLoad
        protected override void LoadDefaultConfig()
        {
            Cfg = new ConfigFile();
            Puts("Loaded default configuration file");
        }
        protected override void SaveConfig() => Config.WriteObject(Cfg);
        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                Cfg = Config.ReadObject<ConfigFile>();
            }
            catch (JsonException ex)
            {
                Puts(ex.Message);
                PrintError("Your config file contains errors!");
                return;
            }
            catch (Exception ex)
            {
                Puts(ex.Message);
                LoadDefaultConfig();
            }

            if (Cfg == null)
            {
                Puts("Config is null");
                LoadDefaultConfig();
            }

            SaveConfig();
        }

        static ConfigFile Cfg = new ConfigFile();

        class ConfigFile
        {
            [JsonProperty(PropertyName = "Prevent selling damaged items")]
            public bool preventDamaged = false;
            [JsonProperty(PropertyName = "Default home category")]
            public string defaultHome = "Resources";
            [JsonProperty(PropertyName = "Log vendor update info")]
            public bool showUpdates = true;
            [JsonProperty(PropertyName = "Allow owner to edit prices in ui?")]
            public bool allowEdits = true;
            [JsonProperty(PropertyName = "Allow access to NPC vendors?")]
            public bool allowNPCs = true;
            [JsonProperty(PropertyName = "Show stock amount in UI?")]
            public bool showStock = true;

        }
        class StoredData
        {
            public List<ulong> Players = new List<ulong>();
            public Dictionary<ulong, PlayerFavorite> fav = new Dictionary<ulong, PlayerFavorite>();
        }

        StoredData storedData;
        private NumberFormatInfo nfi = new CultureInfo("en-GB", false).NumberFormat;
        private Dictionary<ulong, VendingMachine> VendorList = new Dictionary<ulong, VendingMachine>();
        private Dictionary<int, List<ulong>> VendorItemList = new Dictionary<int, List<ulong>>();
        private List<KeyValuePair<int, List<ulong>>> SortedVendorList = new List<KeyValuePair<int, List<ulong>>>();
        private DateTime LastRefreshTime = DateTime.Now.AddHours(-2);
        private List<string> categoryList = new List<string>();
        private Dictionary<string, ProtoBuf.VendingMachine.SellOrder> CurrentEditOrders = new Dictionary<string, ProtoBuf.VendingMachine.SellOrder>();
        private Dictionary<ulong, FavoriteItem> currentPlayerFav = new Dictionary<ulong, FavoriteItem>();
        private Dictionary<ulong, string> currentPlayerSell = new Dictionary<ulong, string>();
        private HashSet<ulong> taintedVendorIds = new HashSet<ulong>();

        class PlayerFavorite
        {
            public FavoriteItem f1 { get; set; }
            public FavoriteItem f2 { get; set; }
            public FavoriteItem f3 { get; set; }
            public FavoriteItem f4 { get; set; }
            public FavoriteItem f5 { get; set; }
        }
        class FavoriteItem
        {
            public int itemSoldId { get; set; }
            public string itemCat { get; set; }
            public string vendorNetId { get; set; }
            public string consoleCommand { get; set; }

            public string toString()
            {
                switch (consoleCommand)
                {
                    case "tradeui.openhomecat":
                        return "Category \t'" + itemCat + "'";
                    case "tradeui.openvendor":
                        VendingMachine v = Plugin.VendorList[Convert.ToUInt64(vendorNetId)];
                        if (v == null) return "Vendor not existing";
                        return "Vendor \t\t'" + v.shopName + "'";
                    case "tradeui.openvendorlist":
                        return "Item \t\t'" + ItemManager.itemDictionary[itemSoldId].displayName.translated + "'";
                    default:
                        return "FalseCommandSaved";
                }
            }

            public void runCommand(BasePlayer player)
            {
                switch (consoleCommand)
                {
                    case "tradeui.openhomecat":
                        player.SendConsoleCommand("tradeui.openhomecat", (object)itemCat);
                        break;
                    case "tradeui.openvendor":
                        Plugin.timer.Once(0.5f, () => {
                            player.SendConsoleCommand("tradeui.openvendor", (object)vendorNetId);
                        });
                        break;
                    case "tradeui.openvendorlist":
                        player.SendConsoleCommand("tradeui.openvendorlist", (object)itemSoldId, (object)itemCat);
                        break;
                }
            }
        }
        void Loaded()
        {
            Cfg = Config.ReadObject<ConfigFile>();
            Plugin = this;
            permission.RegisterPermission(permUse, this);

            storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("TradeUI");
            SaveData();

            nfi.NumberDecimalSeparator = ",";
            nfi.NumberGroupSeparator = ".";
            nfi.NumberDecimalDigits = 0;

            updateVendorList();
        }
        private void OnServerInitialized()
        {
            // preload item icons - this might be excessive, but the list is very dynamic otherwise
            // this way the load should only happen once and have all icons prewarmed
            List<KeyValuePair<string, ulong>> itemIconList = ItemManager.GetItemDefinitions().Select(itemDef => new KeyValuePair<string, ulong>(itemDef.shortname, 0)).ToList();
        }
        void Unload()
        {
            if (UiPlayers.Count <= 0) return;
            foreach (var player in UiPlayers.ToList())
            {
                killUI(player);
            }
        }

        void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("TradeUI", storedData);
        }

        #endregion

        #region Hooks

        object CanVendingAcceptItem(VendingMachine vending, Item item, int targetPos)
        {
            //This prevents vendors globally from accepting damaged goods, if configured;
            if (!Cfg.preventDamaged) return null;
            if (item.info.condition.enabled && item.condition < item.info.condition.max - 5f)
            {
                SendReply(item.parent.playerOwner, "You can't sell damaged goods! Use /fix to repair.");
                return false;
            }
            return null;
        }
        object CanLootEntity(BasePlayer player, StorageContainer container)
        {
            if (container == null || !(container is NPCVendingMachine)) return null;
            if (!(container is InvisibleVendingMachine)) return null;
            InvisibleVendingMachine v = container as InvisibleVendingMachine;
            if (!v.CanOpenLootPanel(player, v.customerPanel) || !player.inventory.loot.StartLootingEntity((BaseEntity)v, false))
                return false;
            v.SetFlag(BaseEntity.Flags.Open, true, false, true);
            v.AddContainers(player.inventory.loot);
            player.inventory.loot.SendImmediate();
            player.ClientRPCPlayer<string>((Connection)null, player, "RPC_OpenLootPanel", v.customerPanel);
            v.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            return true;
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            killUI(player);
            clearPlayerSell(player);
        }
        private object OnEntityVisibilityCheck(BaseEntity entity, BasePlayer player, uint rpcId, string debugName, float maximumDistance)
        {
            if (entity is VendingMachine)
            {
                return true;
            }
            return null;
        }
        object OnBuyVendingItem(VendingMachine machine, BasePlayer player, int sellOrderId, int numberOfTransactions)
        {
            if (machine is InvisibleVendingMachine)
            {
                InvisibleVendingMachine im = machine as InvisibleVendingMachine;
            }
            machine.SetPendingOrder(player, sellOrderId, numberOfTransactions);
            DoTransaction(machine, player, sellOrderId, numberOfTransactions);
            machine.ClearPendingOrder();
            var finaleffect = new Effect("assets/prefabs/deployable/vendingmachine/effects/vending-machine-purchase-human.prefab", player, 0, Vector3.zero, Vector3.forward);
            EffectNetwork.Send(finaleffect, player.net.connection);

            Decay.RadialDecayTouch(machine.transform.position, 40f, 2097408);
            return true;
        }
        #endregion

        #region Commands

        [ConsoleCommand("tradeui.close")]
        private void CmdClose(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            killUI(player);
            player.ClientRPCPlayer(null, player, "OnRespawnInformation", new RespawnInformation { spawnOptions = new List<RespawnInformation.SpawnOptions>() }.ToProtoBytes());
        }
        [ConsoleCommand("tradeui.closeedit")]
        private void CmdCloseEdit(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            CuiHelper.DestroyUi(player, mainName + "_offer");
        }
        [ConsoleCommand("tradeui.closesell")]
        private void CmdCloseSell(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            CuiHelper.DestroyUi(player, mainName + "_sell");
        }
        [ConsoleCommand("tradeui.opensell")]
        private void CmdOpenSell(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string itemShortname = arg.GetString(0);
            CuiHelper.DestroyUi(player, mainName + "_sell");
            if (itemShortname == null) return;

            currentPlayerSell[player.userID] = itemShortname;
            reloadUI(player);
        }
        [ConsoleCommand("tradeui.opensellfilter")]
        private void CmdOpenSellFilter(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            CuiHelper.DestroyUi(player, mainName + "_sell");
            displaySellUI(player);
        }
        [ConsoleCommand("tradeui.clearsellfilter")]
        private void CmdClearSellFilter(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            clearPlayerSell(player);
            reloadUI(player);
        }
        [ConsoleCommand("tradeui.back")]
        private void CmdBack(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string itemCat = arg.GetString(0);

            CuiHelper.DestroyUi(player, mainName + "_shop");
            GUIHomeElement(player, mainName + "_home", itemCat);
            player.ClientRPCPlayer(null, player, "OnRespawnInformation", new RespawnInformation { spawnOptions = new List<RespawnInformation.SpawnOptions>() }.ToProtoBytes());

            currentPlayerFav[player.userID] = new FavoriteItem { itemCat = itemCat, consoleCommand = "tradeui.openhomecat" };
        }

        [ConsoleCommand("tradeui.openhomecat")]
        private void CmdOpenHomeCat(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string itemCat = arg.GetString(0);

            CuiHelper.DestroyUi(player, mainName + "_home");
            GUIHomeElement(player, mainName + "_home", itemCat);
            currentPlayerFav[player.userID] = new FavoriteItem { itemCat = itemCat, consoleCommand = "tradeui.openhomecat" };
        }

        [ConsoleCommand("tradeui.openvendorlist")]
        private void CmdOpenVendorList(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            int itemSoldId = arg.GetInt(0);
            string itemCat = arg.GetString(1);

            CuiHelper.DestroyUi(player, mainName + "_home");
            GUIShopElement(player, mainName + "_shop", itemSoldId, itemCat);
            currentPlayerFav[player.userID] = new FavoriteItem { itemSoldId = itemSoldId, itemCat = itemCat, consoleCommand = "tradeui.openvendorlist" };

        }

        [ConsoleCommand("tradeui.openvendor")]
        private void CmdOpenVendor(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string vendorNetId = arg.GetString(0);
            VendingMachine v = VendorList[Convert.ToUInt64(vendorNetId)];

            /*  Net manipulation -> no longer required? 
            if (!v.net.group.subscribers.Contains(player.net.connection))
            {
                v.net.group.AddSubscriber(player.net.connection);
                v.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            }
            */
            player.net.SwitchSecondaryGroup(v.net.group);
            player.ClientRPCPlayer(null, player, "RPC_OpenShop", Convert.ToUInt64(vendorNetId));
            OpenVendorUI(player, v);
            currentPlayerFav[player.userID] = new FavoriteItem { vendorNetId = vendorNetId, consoleCommand = "tradeui.openvendor" };

        }
        [ConsoleCommand("tradeui.editoffer")]
        private void CmdEditOffer(ConsoleSystem.Arg arg)
        {
            if (!Cfg.allowEdits) return;
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string vendorNetId = arg.GetString(0);
            string sellOrderId = arg.GetString(1);
            VendingMachine v = VendorList[Convert.ToUInt64(vendorNetId)];
            if (v == null) return;
            if (v.OwnerID == 0 && !player.IsAdmin || v.OwnerID != 0 && v.OwnerID != player.userID) return;

            GUIOfferElement(player, mainName + "_offer", v, sellOrderId);

        }


        [ConsoleCommand("tradeui.editofferinput")]
        private void CmdEditOfferInput(ConsoleSystem.Arg arg)
        {
            if (!Cfg.allowEdits) return;
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;

            string vendorNetId = arg.GetString(0);
            string itemOrPrice = arg.GetString(1);
            string sellOrderId = arg.GetString(2);
            string amount = arg.GetString(3);

            VendingMachine v = VendorList[Convert.ToUInt64(vendorNetId)];
            if (v == null) return;
            if (v.OwnerID == 0 && !player.IsAdmin || v.OwnerID != 0 && v.OwnerID != player.userID) return;

            int amountNum = 0;

            if (!int.TryParse(amount, out amountNum))
            {
                CuiHelper.DestroyUi(player, mainName + "_offer");
                GUIOfferElement(player, mainName + "_offer", v, sellOrderId, "Entry must be a number!");
                return;
            }
            if (amountNum < 1 || amountNum > 99999)
            {
                CuiHelper.DestroyUi(player, mainName + "_offer");
                GUIOfferElement(player, mainName + "_offer", v, sellOrderId, "Entry must be between 1 and 99999!");
                return;
            }

            ProtoBuf.VendingMachine.SellOrder thisOrder = CurrentEditOrders[sellOrderId];
            if (thisOrder == null)
            {
                CuiHelper.DestroyUi(player, mainName + "_offer");
                GUIOfferElement(player, mainName + "_offer", v, sellOrderId, "Invalid sell order!");
                return;
            }
            if (itemOrPrice == "item")
            {
                thisOrder.itemToSellAmount = amountNum;
            }
            else
            {
                thisOrder.currencyAmountPerItem = amountNum;
            }
            v.SendNetworkUpdateImmediate();
            CuiHelper.DestroyUi(player, mainName + "_offer");
            string itemCat = ItemManager.itemDictionary[thisOrder.itemToSellID].category.ToString("G");

            //Puts("DEBUG: - " + itemCat + " itemAmnt " + thisOrder.itemToSellAmount + " for " + thisOrder.currencyAmountPerItem);

            CuiHelper.DestroyUi(player, mainName + "_shop");
            GUIShopElement(player, mainName + "_shop", thisOrder.itemToSellID, itemCat);
        }


        [ConsoleCommand("tradeui.savefav")]
        private void CmdSaveFavorite(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string favstring = arg.GetString(0);
            //initial save
            if (!storedData.fav.ContainsKey(player.userID))
            {
                storedData.fav[player.userID] = new PlayerFavorite();
            }
            // no current?
            if (!currentPlayerFav.ContainsKey(player.userID))
            {
                currentPlayerFav[player.userID] = new FavoriteItem();
            }

            switch (favstring)
            {
                case "f1":
                    storedData.fav[player.userID].f1 = currentPlayerFav[player.userID];
                    break;
                case "f2":
                    storedData.fav[player.userID].f2 = currentPlayerFav[player.userID];
                    break;
                case "f3":
                    storedData.fav[player.userID].f3 = currentPlayerFav[player.userID];
                    break;
                case "f4":
                    storedData.fav[player.userID].f4 = currentPlayerFav[player.userID];
                    break;
                case "f5":
                    storedData.fav[player.userID].f5 = currentPlayerFav[player.userID];
                    break;
                default:
                    ShowInfoPopup(player, "Error, wrong favorite", true);
                    return;
            }

            string msg = "Saving " + favstring;
            msg += "\n<color=white>(check </color><color=orange>/trade info</color><color=white> for details)</color>";
            ShowInfoPopup(player, msg);
            SaveData();
        }
        [ChatCommand("sell")]
        void CmdTradeSell(BasePlayer player, string command, string[] args)
        {
            if (!permCheckVerbose(player, permUse)) return;
            displaySellUI(player);
        }

        [ChatCommand("trade")]
        void CmdTradeUI(BasePlayer player, string command, string[] args)
        {
            if (!permCheckVerbose(player, permUse)) return;
            updateVendorList();
            if(args.Length == 0)
            {
                currentPlayerFav[player.userID] = new FavoriteItem { itemCat = Cfg.defaultHome, consoleCommand = "tradeui.openhomecat" };
                reloadUI(player, "test");
                return;
            }
            //open fav
            if(args.Length == 1)
            {
                switch (args[0])
                {
                    case "f1":
                        currentPlayerFav[player.userID] = storedData.fav[player.userID].f1;
                        break;
                    case "f2":
                        currentPlayerFav[player.userID] = storedData.fav[player.userID].f2;
                        break;
                    case "f3":
                        currentPlayerFav[player.userID] = storedData.fav[player.userID].f3;
                        break;
                    case "f4":
                        currentPlayerFav[player.userID] = storedData.fav[player.userID].f4;
                        break;
                    case "f5":
                        currentPlayerFav[player.userID] = storedData.fav[player.userID].f5;
                        break;
                    case "info":
                        getFavInfo(player);
                        return;
                    default:
                        SendReply(player, " <color=red>ERROR:</color> usage example <color=green>/trade f1</color> (f1 to f5)");
                        return;
                }
            }
            if(currentPlayerFav[player.userID] == null)
            {
                currentPlayerFav[player.userID] = new FavoriteItem { itemCat = Cfg.defaultHome, consoleCommand = "tradeui.openhomecat" };
            }
            reloadUI(player, "test");
            currentPlayerFav[player.userID].runCommand(player);


        }

        #endregion

        #region Functions
        private void ShowInfoPopup(BasePlayer player, string msg, bool isError = false)
        {

            timer.Once(1f, () => {
                CuiElementContainer GUITEXT = new CuiElementContainer();
                string color = (isError) ? "1 0 0 1" : "0 9 0 1";
                //GUITEXT = new CuiElementContainer();

                GUITEXT.Add(new CuiPanel
                {
                    Image =
                    {
                        Color = "0 0 0 0.9",
                        FadeIn = 0.5f
                    },
                    RectTransform =
                    {
                        AnchorMin = "0.3 0.7",
                        AnchorMax = "0.7 0.8"
                    },
                    CursorEnabled = false
                }, "Overlay", "AnnouncementText");
                GUITEXT.Add(new CuiLabel
                {
                    Text =
                    {
                        Text = msg,
                        FontSize = 18,
                        Align = TextAnchor.MiddleCenter,
                        Color = color,
                        FadeIn = 0.9f
                    },
                    RectTransform =
                    {
                        AnchorMin = "0 0",
                        AnchorMax = "1 1"
                    }
                }, "AnnouncementText");

                CuiHelper.DestroyUi(player, "AnnouncementText");
                CuiHelper.AddUi(player, GUITEXT);

                timer.Once(5f, () => {
                    CuiHelper.DestroyUi(player, "AnnouncementText");
                });

            });
        }

        public bool DoTransaction(VendingMachine vm, BasePlayer buyer, int sellOrderId, int numberOfTransactions = 1)
        {
            if (sellOrderId < 0 || sellOrderId > vm.sellOrders.sellOrders.Count)
                return false;
            object obj1 = Interface.CallHook("OnVendingTransaction", (object)vm, (object)buyer, (object)sellOrderId, (object)numberOfTransactions);
            if (obj1 is bool)
                return (bool)obj1;
            ProtoBuf.VendingMachine.SellOrder sellOrder = vm.sellOrders.sellOrders[sellOrderId];
            List<Item> source1 = vm.inventory.FindItemsByItemID(sellOrder.itemToSellID);
            if (sellOrder.itemToSellIsBP)
                source1 = vm.inventory.FindItemsByItemID(vm.blueprintBaseDef.itemid).Where<Item>((Func<Item, bool>)(x => x.blueprintTarget == sellOrder.itemToSellID)).ToList<Item>();
            if (source1 == null || source1.Count == 0)
                return false;
            numberOfTransactions = Mathf.Clamp(numberOfTransactions, 1, source1[0].hasCondition ? 1 : 1000000);
            int num1 = sellOrder.itemToSellAmount * numberOfTransactions;
            int num2 = source1.Sum<Item>((Func<Item, int>)(x => x.amount));
            if (num1 > num2)
                return false;
            List<Item> source2 = buyer.inventory.FindItemsByItemID(sellOrder.currencyID);
            if (sellOrder.currencyIsBP)
                source2 = buyer.inventory.FindItemsByItemID(vm.blueprintBaseDef.itemid).Where<Item>((Func<Item, bool>)(x => x.blueprintTarget == sellOrder.currencyID)).ToList<Item>();
            List<Item> list = source2.Where<Item>((Func<Item, bool>)(x =>
            {
                if (!x.hasCondition)
                    return true;
                if ((double)x.conditionNormalized >= 0.5)
                    return (double)x.maxConditionNormalized > 0.5;
                return false;
            })).ToList<Item>();
            if (list.Count == 0)
                return false;
            int num3 = list.Sum<Item>((Func<Item, int>)(x => x.amount));
            int num4 = sellOrder.currencyAmountPerItem * numberOfTransactions;
            int num5 = num4;
            if (num3 < num5)
                return false;
            vm.transactionActive = true;
            int num6 = 0;
            foreach (Item obj2 in list)
            {
                int split_Amount = Mathf.Min(num4 - num6, obj2.amount);
                vm.TakeCurrencyItem(obj2.amount > split_Amount ? obj2.SplitItem(split_Amount) : obj2);
                num6 += split_Amount;
                if (num6 >= num4)
                    break;
            }
            int num7 = 0;
            foreach (Item obj2 in source1)
            {
                int split_Amount = num1 - num7;
                Item soldItem = obj2.amount > split_Amount ? obj2.SplitItem(split_Amount) : obj2;
                if (soldItem == null)
                {
                    Debug.LogError((object)"Vending machine error, contact developers!");
                }
                else
                {
                    num7 += soldItem.amount;
                    vm.GiveSoldItem(soldItem, buyer);
                }
                if (num7 >= num1)
                    break;
            }
            vm.UpdateEmptyFlag();
            vm.transactionActive = false;
            return true;
        }

        private void updateVendorList()
        {
            if ((DateTime.Now - LastRefreshTime).TotalSeconds < 60) return;

            var Vendors = Resources.FindObjectsOfTypeAll<VendingMachine>();
            VendorItemList?.Clear();
            categoryList?.Clear();

            foreach (VendingMachine v in Vendors)
            {
                if (v.net == null) continue;
                if (!v.IsBroadcasting()) continue;
                if(!Cfg.allowNPCs && v.OwnerID == 0) continue;
                // v.globalBroadcast = true;
                // v.UpdateNetworkGroup();
                if(v.globalBroadcast)
                {
                    v.globalBroadcast = false;
                    v.UpdateNetworkGroup();
                }

                if (!VendorList.ContainsKey(v.net.ID.Value))
                {
                    VendorList.Add(v.net.ID.Value, v);
                }
                foreach (ProtoBuf.VendingMachine.SellOrder sellOrder in v.sellOrders.sellOrders)
                {
                    if (sellOrder.inStock < 1) continue;
                    if (VendorItemList.ContainsKey(sellOrder.itemToSellID))
                    {
                        if (VendorItemList[sellOrder.itemToSellID].Contains(v.net.ID.Value)) continue;
                        VendorItemList[sellOrder.itemToSellID].Add(v.net.ID.Value);
                    }
                    else
                    {
                        VendorItemList.Add(sellOrder.itemToSellID, new List<ulong>() { v.net.ID.Value });
                    }
                    if (!categoryList.Contains(ItemManager.itemDictionary[sellOrder.itemToSellID].category.ToString("G")))
                    {
                        categoryList.Add(ItemManager.itemDictionary[sellOrder.itemToSellID].category.ToString("G"));
                    }
                }
            }
            SortedVendorList = VendorItemList.OrderBy(o => ItemManager.itemDictionary[o.Key].displayName.translated).ToList();
            categoryList.Sort();

            if(Cfg.showUpdates) Puts("INFO: Updated vendors after " + (DateTime.Now - LastRefreshTime).TotalSeconds + "s of inactivity - found: " +VendorList.Count());
            LastRefreshTime = DateTime.Now;
        }


        private void OpenVendorUI(BasePlayer player, VendingMachine v)
        {
            // v.globalBroadcast = true;
            // v.UpdateNetworkGroup();
            if(v.globalBroadcast)
            {
                v.globalBroadcast = false;
                v.UpdateNetworkGroup();
            }
            v.SendSellOrders(player);
            v.PlayerOpenLoot(player, v.customerPanel, false);
            Interface.CallHook("OnOpenVendingShop", (object)v, (object)player);
        }

        private bool permCheckVerbose(BasePlayer player, string perm)
        {
            if (HasPermission(player.UserIDString, perm)) return true;
            SendReply(player, "No permission to use this command!");
            return false;
        }

        private string getSellOrderId(ulong vid, ProtoBuf.VendingMachine.SellOrder s)
        {
            string sid = vid + "s" + s.itemToSellID + "a" + s.itemToSellAmount + "c" + s.currencyID + "p" + s.currencyAmountPerItem + "b" + s.currencyIsBP;
            if (!CurrentEditOrders.ContainsKey(sid))
            {
                CurrentEditOrders.Add(sid, s);
            }
            return sid;
        }

        private void getFavInfo(BasePlayer player)
        {

            string msg = "<color=orange>============ TradeUI (v" + Plugin.Version + ") ============</color>";
            if (!(storedData.fav.ContainsKey(player.userID)))
            {
                msg += "\nYou don't have any favorites yet.\nSet them via <color=green>/trade</color> GUI";
            }
            else
            {
                PlayerFavorite pf = storedData.fav[player.userID];
                msg += "\nF1: " + ((pf.f1 != null) ? pf.f1.toString() : "not set");
                msg += "\nF2: " + ((pf.f2 != null) ? pf.f2.toString() : "not set");
                msg += "\nF3: " + ((pf.f3 != null) ? pf.f3.toString() : "not set");
                msg += "\nF4: " + ((pf.f4 != null) ? pf.f4.toString() : "not set");
                msg += "\nF5: " + ((pf.f5 != null) ? pf.f5.toString() : "not set");
            }
            SendReply(player, msg);
        }

        private void clearPlayerSell(BasePlayer player)
        {
            if (currentPlayerSell.ContainsKey(player.userID)) currentPlayerSell.Remove(player.userID);
        }
        #endregion

        #region GUI

        private const string globalNoErrorString = "none";
        private const string mainName = "TradeUI";


        private HashSet<BasePlayer> UiPlayers = new HashSet<BasePlayer>();
        private string[] uiElements =
        {
            mainName+"_bg",
            mainName+"_head",
            mainName+"_home",
            mainName+"_shop",
            mainName+"_offer",
            mainName+"_foot",
            mainName+"_sell"
        };
        private float globalLeftBoundary = 0.1f;
        private float globalRighttBoundary = 0.9f;
        private float globalTopBoundary = 0.95f;
        private float globalBottomBoundary = 0.1f;
        private float globalSpace = 0.01f;
        private float eContentWidth = 0.395f;
        private float eControlWidth = 0.15f;
        private float eHeadHeight = 0.05f;
        private float eFootHeight = 0.05f;
        private float eSlotHeight = 0.123f;


        private void reloadUI(BasePlayer player, string errorMsg = globalNoErrorString)
        {
            if (!UiPlayers.Contains(player))
            {
                UiPlayers.Add(player);
            }
            foreach (string ui in uiElements)
            {
                CuiHelper.DestroyUi(player, ui);
            }
            displayUI(player, errorMsg);

        }
        private void killUI(BasePlayer player)
        {
            foreach (string ui in uiElements)
            {
                CuiHelper.DestroyUi(player, ui);
            }
            if (UiPlayers.Contains(player))
            {
                UiPlayers.Remove(player);
            }
        }

        private string numberCandy(int number)
        {
            return Convert.ToDecimal(number).ToString("N", nfi);
        }
        private void displayUI(BasePlayer player, string errorMsg = globalNoErrorString)
        {
            //GUIOverlayElement(player, mainName+"_bg");
            GUIHeaderElement(player, mainName + "_head");
            GUIHomeElement(player, mainName + "_home", Cfg.defaultHome);
            GUIFooterElement(player, mainName + "_foot");
        }
        private void displaySellUI(BasePlayer player, string errorMsg = globalNoErrorString)
        {
            if (!UiPlayers.Contains(player))
            {
                UiPlayers.Add(player);
            }
            CuiHelper.DestroyUi(player, mainName + "_sell");
            GUISellElement(player, mainName + "_sell");
        }

        private void GUIHeaderElement(BasePlayer player, string elUiId)
        {

            var elements = new CuiElementContainer();
            elements.Add(new CuiPanel
            {
                Image =
                {
                    Color = "0.12 0.56 0.12 1",
                    Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                },
                RectTransform =
                {
                    AnchorMin = "0 " + (1f-eHeadHeight),
                    AnchorMax = "1 " + (1f)
                },
                CursorEnabled = true
            }, "Overlay", elUiId);
            elements.Add(new CuiLabel
            {
                Text =
                {
                    Text = "Global /trade System",
                    FontSize = 18,
                    Align = TextAnchor.MiddleLeft,
                    Color = "1 1 1 1"
                },
                RectTransform =
                {
                    AnchorMin = "0.01 0",
                    AnchorMax = "1 1"
                }
            }, elUiId);

            elements.Add(new CuiLabel
            {
                Text =
                {
                    Text = Plugin.Name +" v" + Plugin.Version + " by " + Plugin.Author,
                    FontSize = 10,
                    Align = TextAnchor.MiddleRight,
                    Color = "1 1 1 1"
                },
                RectTransform =
                {
                    AnchorMin = "0 0",
                    AnchorMax = "0.99 1"
                }
            }, elUiId);


            //Favorites items
            elements.Add(new CuiLabel
            {
                Text =
                {
                    Text = "Set current page as favorite: (open with - /trade f1...f5)",
                    FontSize = 10,
                    Align = TextAnchor.MiddleLeft,
                    Color = "1 1 1 1"
                },
                RectTransform =
                {
                    AnchorMin = "0.35 0",
                    AnchorMax = "0.65 1"
                }
            }, elUiId);
            elements.Add(new CuiPanel
            {
                Image =
                {
                    Color = "0 0 0 0",
                },
                RectTransform =
                {
                    AnchorMin = "0.35 0",
                    AnchorMax = "0.65 0.3"
                },
                CursorEnabled = true
            }, elUiId, elUiId + "_scaler");

            float localLeft = 0.0f;
            for (int i = 1; i < 6; i++)
            {
                elements.Add(new CuiButton
                {
                    Button =
                    {
                        Command = "tradeui.savefav f" + i,
                        Color = "0.8 0.8 0.8 0.6"
                    },
                    RectTransform =
                    {
                        AnchorMin = localLeft + " 0",
                        AnchorMax = (localLeft+0.17f) + " 1"
                    },
                    Text =
                    {
                        Text = "F" + i ,
                        FontSize = 8,
                        Align = TextAnchor.MiddleCenter,
                        Color = "1 1 1 1"
                    }
                }, elUiId + "_scaler");
                localLeft += 0.18f;
            }

            CuiHelper.AddUi(player, elements);
        }
        private void GUIOverlayElement(BasePlayer player, string elUiId)
        {

            var elements = new CuiElementContainer();
            elements.Add(new CuiPanel
            {
                Image =
                {
                    Color = "0 0 0 1",
                },
                RectTransform =
                {
                    AnchorMin = "0 0",
                    AnchorMax = "1 1"
                },
                CursorEnabled = true
            }, "Hud", elUiId);

            CuiHelper.AddUi(player, elements);
        }
        private void GUIFooterElement(BasePlayer player, string elUiId)
        {

            var elements = new CuiElementContainer();
            elements.Add(new CuiPanel
            {
                Image =
                {
                    Color = "0 0 0 1",
                    Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                },
                RectTransform =
                {
                    AnchorMin = "0 0",
                    AnchorMax = "1 " + (eFootHeight)
                },
                CursorEnabled = true
            }, "Overlay", elUiId);

            var closeButton = new CuiButton
            {
                Button =
                {
                    Command = "tradeui.close",
                    Color = "0.56 0.12 0.12 1"
                },
                RectTransform =
                {
                    AnchorMin = "0 0",
                    AnchorMax = "1 1"
                },
                Text =
                {
                    Text = "CLOSE",
                    FontSize = 12,
                    Align = TextAnchor.MiddleCenter,
                    Color = "1 1 1 1"
                }
            };
            elements.Add(closeButton, elUiId);

            CuiHelper.AddUi(player, elements);
        }

        private void GUIHomeElement(BasePlayer player, string elUiId, string currentCategory)
        {
            var elements = new CuiElementContainer();

            float topBoundary = globalTopBoundary - eHeadHeight - globalSpace;
            float botBoundary = globalBottomBoundary + eFootHeight + globalSpace;

            elements.Add(new CuiPanel
            {
                Image =
                {
                    Color = "0 0 0 0.5",
                    Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
                },
                RectTransform =
                {
                    AnchorMin = "0 0",
                    AnchorMax = "1 " + (1f-eHeadHeight)
                },
                CursorEnabled = true
            }, "Hud", elUiId);

            float contentStart = 0.97f;
            float itemsPerRow = 15f;
            float tabWidth = 1f / 16f;
            float tabHeight = 0.03f;
            float cellWidth = 0.9f / (itemsPerRow + 1f);
            float buttonHeight = 1.5f * cellWidth;
            float leftBoundary = 0.02f;
            float leftWidth = 0.95f;
            float space = 0.005f;

            int numItems = 0;
            List<KeyValuePair<int, List<ulong>>> sortedItems = new List<KeyValuePair<int, List<ulong>>>();
            int totalItems = 0;
            Dictionary<string, int> catItems = new Dictionary<string, int>();
            // switch between filter view
            foreach (KeyValuePair<int, List<ulong>> kv in SortedVendorList)
            {
                if (!catItems.ContainsKey(ItemManager.itemDictionary[kv.Key].category.ToString("G")))
                {
                    catItems.Add(ItemManager.itemDictionary[kv.Key].category.ToString("G"), 0);
                }

                if (currentPlayerSell.ContainsKey(player.userID))
                {
                    HashSet<int> tempItemsAdded = new HashSet<int>();
                    foreach (ulong vID in kv.Value)
                    {
                        foreach (ProtoBuf.VendingMachine.SellOrder s in VendorList[vID].sellOrders.sellOrders)
                        {
                            if (s.itemToSellID != kv.Key) continue;
                            if (ItemManager.itemDictionary[s.currencyID].shortname == currentPlayerSell[player.userID])
                            {
                                totalItems++;
                                if (!tempItemsAdded.Contains(kv.Key)) {
                                    sortedItems.Add(kv);
                                    tempItemsAdded.Add(kv.Key);
                                    catItems[ItemManager.itemDictionary[kv.Key].category.ToString("G")] += 1;
                                }
                            }
                        }
                    }
                }
                else
                {
                    catItems[ItemManager.itemDictionary[kv.Key].category.ToString("G")] += 1;
                }
            }
            if (!currentPlayerSell.ContainsKey(player.userID))
            {
                sortedItems = SortedVendorList;
                totalItems = sortedItems.Count();
            }

            if(totalItems > 50)
            {
                foreach (string catName in categoryList)
                {
                    if (!catItems.ContainsKey(catName) || catItems[catName] <= 0) continue;

                    float localLeftBoundary = (float)(leftBoundary + (numItems % itemsPerRow * (tabWidth + space)));
                    string buttonColor = (catName == currentCategory) ? "0.7 0.38 0 1" : "0.3 0.3 0.3 1";

                    elements.Add(new CuiButton
                    {
                        Button =
                        {
                            Command = "tradeui.openhomecat " + catName,
                            Color = buttonColor
                        },
                        RectTransform =
                        {
                            AnchorMin = localLeftBoundary +" "+ (contentStart-tabHeight),
                            AnchorMax = (localLeftBoundary + tabWidth) + " "+ contentStart
                        },
                        Text =
                        {
                            Text = catName + " ("+catItems[catName]+")",
                            FontSize = 10,
                            Align = TextAnchor.MiddleCenter,
                            Color = "1 1 1 1"
                        }
                    }, elUiId);

                    numItems++;
                }
                contentStart = contentStart - buttonHeight;
            }
            else if (totalItems <= 0 && currentPlayerSell.ContainsKey(player.userID))
            {
                elements.Add(new CuiLabel
                {
                    Text =
                {
                    Text = "No items for sale for " + ItemManager.itemDictionaryByName[currentPlayerSell[player.userID]].displayName.translated,
                    FontSize = 25,
                    Align = TextAnchor.MiddleCenter,
                    Color = "1 1 1 1"
                },
                    RectTransform =
                {
                    AnchorMin = "0.005 0.70",
                    AnchorMax = "0.995 0.995"
                }
                }, elUiId);
            }

            numItems = 0;
            foreach (KeyValuePair<int, List<ulong>> kv in sortedItems)
            {
                if (totalItems > 50)
                {
                    if (ItemManager.itemDictionary[kv.Key].category.ToString("G") != currentCategory) continue;
                }
                string sellItemName = ItemManager.itemDictionary[kv.Key].displayName.translated;

                int rowNum = numItems % (int)itemsPerRow;
                int lastRowNum = rowNum;
                int colNum = (int)Math.Floor(numItems / itemsPerRow);

                float localContentStart = (float)(contentStart - (Math.Floor(numItems / itemsPerRow) * (buttonHeight + 3 * space)));
                float localLeftBoundary = (float)(leftBoundary + (numItems % itemsPerRow * (cellWidth + space)));

                // Images
                elements.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = elUiId,
                    Components =
                    {
                        //toDo think about utilizing skins here, too
                        new CuiImageComponent { ItemId = kv.Key, SkinId = 0 },
                        new CuiRectTransformComponent {
                            AnchorMin = (localLeftBoundary+0.005f) +" "+ (localContentStart-buttonHeight+0.01f),
                            AnchorMax = (localLeftBoundary + cellWidth-0.005f) + " "+ localContentStart
                        }
                    }
                });

                elements.Add(new CuiButton
                {
                    Button =
                    {
                        Command = "tradeui.openvendorlist " + kv.Key + " " + currentCategory,
                        Color = "0.7 0.38 0 0"
                    },
                    RectTransform =
                    {
                       
// ... [Code preview truncated due to length. Full source in attached file] ...

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