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

FREE OGSplitter : 1.1.3 1.1.3

Нет прав для скачивания
C#:
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("OGSplitter", "Whispers88", "1.1.3")]
    [Description("Split cookable items")]
    class OGSplitter : CovalencePlugin
    {
        private Configuration config;
        public static OGSplitter _ogSplitter;

        [PluginReference]
        private Plugin OGFurnace;

        public class Configuration
        {
            [JsonProperty("UI Button Splitter Button Min Position")]
            public string UISplitterBtnPosMin = "0.65 0.01";

            [JsonProperty("UI Button Splitter Button Max Position")]
            public string UISplitterBtnPosMax = "0.73 0.06";

            [JsonProperty("UI Button Splitter Button Font Size")]
            public int UISplitterBtnFontSize = 16;

            [JsonProperty("UI Button Splitter Button Text")]
            public string UISplitterBtnText = "Run Splitter";

            [JsonProperty("UI Button Splitter Button Color")]
            public string UISplitterBtnClr = "0.5 0.5 0.5 0.3";

            [JsonProperty("UI Button Splitter Text Color")]
            public string UISplitterBtnTextClr = "0.8 0.8 0.8 0.75";
            public string ToJson() => JsonConvert.SerializeObject(this);

            public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
        }

        protected override void LoadDefaultConfig() => config = new Configuration();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null)
                {
                    throw new JsonException();
                }

                if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys))
                {
                    LogWarning("Configuration appears to be outdated; updating and saving");
                    SaveConfig();
                }
            }
            catch
            {
                LogWarning($"Configuration file {Name}.json is invalid; using defaults");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig()
        {
            LogWarning($"Configuration changes saved to {Name}.json");
            Config.WriteObject(config, true);
        }

        #region INIT
        public string permuse = "ogsplitter.use";
        CuiElementContainer cachedSplitterUI = null;

        private void Init()
        {
            _ogSplitter = this;

            permission.RegisterPermission(permuse, this);
            AddLocalizedCommand(nameof(SplitterCommand));

            // Create a cached version of the UI
            cachedSplitterUI = CreateSplitterUI();
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
                CuiHelper.DestroyUi(player, "SplitterUI");
        }

        #endregion INIT

        #region Localization

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["SplitterCommand"] = "OvenSplitter"

            }, this);
        }

        #endregion Localization

        #region HOOKS

        private void OnLootEntity(BasePlayer player, BaseOven oven)
        {
            if (!HasPerm(player.UserIDString, permuse)) return;
            CuiHelper.AddUi(player, cachedSplitterUI);
        }

        void OnLootEntityEnd(BasePlayer player, BaseOven oven) => CuiHelper.DestroyUi(player, "SplitterUI");

        #endregion HOOKS


        #region SPLITTER METHOD
        public class CookableItem
        {
            public int amount;
            public ItemModCookable cookableMod;
        }
        void OvenSplitter(BaseOven oven, BasePlayer player)
        {
            Dictionary<ItemDefinition, CookableItem> cookableItems = new Dictionary<ItemDefinition, CookableItem>();
            int ovenFuel = 0;
            ItemContainer ovencon = oven.inventory;
            List<Item> returnitems = new List<Item>();
            //Check current oven inventory
            foreach (var item in oven.inventory.itemList)
            {
                if (item.info == oven.fuelType)
                {
                    ovenFuel += item.amount;
                    continue;
                }

                ItemModCookable itemModCookable;
                if (!item.info.shortname.Contains("cooked") && item.info.TryGetComponent<ItemModCookable>(out itemModCookable))
                {
                    CookableItem cookableItem;
                    if (cookableItems.TryGetValue(item.info, out cookableItem))
                    {
                        cookableItem.amount += item.amount;
                    }
                    else
                    {
                        cookableItems.Add(item.info, new CookableItem() { amount = item.amount, cookableMod = itemModCookable });
                    }
                    continue;
                }
                //Return non-cookables
                returnitems.Add(item);
            }

            foreach (var item in returnitems) player.GiveItem(item);

            int cookableTypesCount = cookableItems.Count;
            //Return items if no cookables present
            if (cookableTypesCount == 0)
            {
                foreach (var item in ovencon.itemList)
                {
                    player.GiveItem(item);
                }
                return;
            }

            //Calculate cookable slots per cookable

            int cookableSlots;
            int remainder;

            if (OGFurnace == null)
            {
                cookableSlots = (int)Math.Ceiling((decimal)(oven.inventory.capacity - oven.fuelSlots - oven.outputSlots) / cookableTypesCount);
                remainder = cookableSlots * cookableTypesCount - (oven.inventory.capacity - oven.fuelSlots - oven.outputSlots);
            }
            else
            {
                cookableSlots = (int)Math.Ceiling((decimal)(oven.inventory.capacity - cookableTypesCount - 2) / cookableTypesCount);
                remainder = (cookableSlots * cookableTypesCount) - (oven.inventory.capacity - cookableTypesCount - 2);
            }

            //If no slots left to cook
            if (cookableSlots < 1)
            {
                foreach (var item in ovencon.itemList)
                {
                    player.GiveItem(item);
                }
                return;
            }

            float smelttime = 0f;
            int l = 0;


            //Remove items in oven
            oven.inventory.Clear();
            ItemManager.DoRemoves();

            //Split Cookables
            foreach (var cookable in cookableItems)
            {
                l++;
                int slotamt = (int)Math.Ceiling((decimal)(cookable.Value.amount / cookableSlots));
                //If more ore than room in oven
                if (slotamt > cookable.Key.stackable)
                {
                    GivePlayerItem(player, cookable.Key, cookable.Value.amount - (cookableSlots * cookable.Key.stackable));
                    cookable.Value.amount = cookableSlots * cookable.Key.stackable;
                    slotamt = cookable.Key.stackable;
                }

                for (var i = 0; i < cookableSlots; i++)
                {
                    bool j = (slotamt * cookableSlots + i < cookable.Value.amount);
                    Item splitItem = ItemManager.Create(cookable.Key, slotamt + (j ? 1 : 0), 0uL);
                    if (OGFurnace != null)
                        splitItem.MoveToContainer(ovencon, i + (l - 1) * (cookableSlots + (l > remainder && remainder != 0 ? 1 : 0)), false);
                    else
                        splitItem.MoveToContainer(ovencon, i + oven.fuelSlots + (l - 1) * (cookableSlots + (l > remainder && remainder != 0 ? 1 : 0)), false);
                }
                //If cookable slots is not evenly distributed
                if (cookableSlots != 1 && l == remainder && remainder != 0) cookableSlots -= 1;

                //Get highest cooktime
                bool k = ((slotamt * cookableSlots) < cookable.Value.amount);
                float cooktime = cookable.Value.cookableMod.cookTime * (slotamt + (k ? 1 : 0));
                if (cooktime > smelttime) smelttime = cooktime;
            }

            float fuelUnits = oven.fuelType.GetComponent<ItemModBurnable>().fuelAmount;
            int neededFuel = (int)Math.Ceiling(smelttime * (oven.cookingTemperature / 200f) / fuelUnits);

            //Check fuel required is not greater than max stack
            if (OGFurnace != null)
            {
                if (neededFuel > oven.fuelType.stackable) neededFuel = oven.fuelType.stackable;
            }
            else if (neededFuel > oven.fuelType.stackable * oven.fuelSlots) neededFuel = oven.fuelType.stackable * oven.fuelSlots;

            if (neededFuel < 1) //This shouldn't happen
            {
                if (ovenFuel > 0)
                    GivePlayerItem(player, oven.fuelType, ovenFuel);
                return;
            }

            //If enough fuel is in the furnace
            if (ovenFuel >= neededFuel)
            {
                if (OGFurnace == null)
                {
                    int fueltogive = neededFuel;
                    for (int i = 0; i < oven.fuelSlots; i++)
                    {
                        Item fuelItem = (i == oven.fuelSlots) ? ItemManager.Create(oven.fuelType, fueltogive, 0uL) : ItemManager.Create(oven.fuelType, (int)Math.Floor((decimal)neededFuel / oven.fuelSlots), 0uL);
                        fueltogive -= fuelItem.amount;
                        fuelItem.MoveToContainer(ovencon, i, false);
                    }
                }
                else
                {
                    oven.inventory.AddItem(oven.fuelType, neededFuel, 0UL);
                }

                if (ovenFuel - neededFuel > 0)
                    GivePlayerItem(player, oven.fuelType, ovenFuel - neededFuel);
            }
            //else check players inventory for more fuel
            else
            {
                int playerFuelAmt = 0;
                List<Item> playerFuel = Pool.Get<List<Item>>();
                player.inventory.FindItemsByItemID(playerFuel, oven.fuelType.itemid);
                //count total fuel in the players inventory
                foreach (Item i in playerFuel)
                {
                    playerFuelAmt += i.amount;
                    i.Remove();
                }
                ItemManager.DoRemoves();

                //if inventory fuel + oven fuel is less than required
                if (neededFuel >= playerFuelAmt + ovenFuel)
                {
                    neededFuel = playerFuelAmt + ovenFuel;
                }
                //if inventory fuel + oven fuel is more than required
                if (OGFurnace == null)
                {
                    int fueltogive = neededFuel;
                    for (int i = 0; i < oven.fuelSlots; i++)
                    {
                        Item fuelItem = (i == oven.fuelSlots) ? ItemManager.Create(oven.fuelType, fueltogive, 0uL) : ItemManager.Create(oven.fuelType, (int)Math.Floor((decimal)neededFuel / oven.fuelSlots), 0uL);
                        fueltogive -= fuelItem.amount;
                        fuelItem.MoveToContainer(ovencon, i, false);
                    }
                }
                else
                    oven.inventory.AddItem(oven.fuelType, neededFuel, 0UL);

                if (ovenFuel + playerFuelAmt - neededFuel > 0)
                    GivePlayerItem(player, oven.fuelType, ovenFuel + playerFuelAmt - neededFuel);

                Pool.FreeUnmanaged<Item>(ref playerFuel);
            }
        }

        #endregion SPLITTER METHOD

        #region COMMANDS
        private void SplitterCommand(IPlayer iplayer, string command, string[] args)
        {
            BasePlayer player = (BasePlayer)iplayer.Object;
            BaseOven oven = (player.inventory?.loot?.entitySource as BaseOven) ?? null;
            if (oven == null || !HasPerm(player.UserIDString, permuse)) return;
            OvenSplitter(oven, player);
        }

        #endregion COMMANDS

        #region GUI Panel
        public CuiElementContainer CreateSplitterUI()
        {
            CuiElementContainer elements = new CuiElementContainer();
            string panel = elements.Add(new CuiPanel
            {
                Image = { Color = config.UISplitterBtnClr },
                RectTransform = { AnchorMin = config.UISplitterBtnPosMin, AnchorMax = config.UISplitterBtnPosMax }
            }, "Hud.Menu", "SplitterUI");

            elements.Add(new CuiButton
            {
                Button = { Command = "OvenSplitter", Color = "0.5 0.5 0.5 0.0" },
                Text = { Text = config.UISplitterBtnText, FontSize = config.UISplitterBtnFontSize, Align = TextAnchor.MiddleCenter, Color = config.UISplitterBtnTextClr },
                RectTransform = { AnchorMin = "0.00 0.00", AnchorMax = "1.0 1.0" }
            }, panel);

            return elements;
        }

        #endregion GUI Panel

        #region HELPERS

        private void GivePlayerItem(BasePlayer player, ItemDefinition itemDef, int amount)
        {
            int freeslots = FreeSlots(player);
            List<int> stacks = GetStacks(itemDef, amount);
            foreach (var stack in stacks)
            {
                if (freeslots < 1)
                {
                    DropItem(player, itemDef, stack);
                    continue;
                }
                freeslots -= 1;
                player.GiveItem(ItemManager.Create(itemDef, stack, 0uL));
            }
        }
        private void DropItem(BasePlayer player, ItemDefinition item, int amount)
        {
            Item itemgive = ItemManager.Create(ItemManager.FindItemDefinition(item.itemid), amount, 0uL);
            Vector3 dropPosition = player.GetDropPosition();
            Vector3 dropVelocity = player.GetDropVelocity();
            itemgive.Drop(dropPosition, dropVelocity, Quaternion.identity);
        }
        private int FreeSlots(BasePlayer player)
        {
            var slots = player.inventory.containerMain.capacity + player.inventory.containerBelt.capacity;
            var taken = player.inventory.containerMain.itemList.Count + player.inventory.containerBelt.itemList.Count;
            return slots - taken;
        }

        private List<int> GetStacks(ItemDefinition item, int amount)
        {
            var list = new List<int>();
            var maxStack = item.stackable;

            while (amount > maxStack)
            {
                amount -= maxStack;
                list.Add(maxStack);
            }

            list.Add(amount);

            return list;
        }

        private bool HasPerm(string id, string perm) => permission.UserHasPermission(id, perm);

        private void AddLocalizedCommand(string command)
        {
            foreach (string language in lang.GetLanguages(this))
            {
                Dictionary<string, string> messages = lang.GetMessages(language, this);
                foreach (KeyValuePair<string, string> message in messages)
                {
                    if (message.Key.Equals(command))
                    {
                        if (!string.IsNullOrEmpty(message.Value))
                        {
                            AddCovalenceCommand(message.Value, command);
                        }
                    }
                }
            }
        }
        #endregion HELPERS
    }
}

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