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

FREE OGFurnace : 1.1.0 1.1.0

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

namespace Oxide.Plugins
{
    [Info("OGFurnace", "Whispers88", "1.1.0")]
    [Description("Brings back the original rust ovens with customizable inventory space")]
    class OGFurnace : CovalencePlugin
    {
        private Configuration config;
        public static OGFurnace _OgFurnace;

        [PluginReference]
        private Plugin FurnaceLevels;

        [PluginReference]
        private Plugin QuickSmelt;

        [PluginReference]
        private Plugin PowerSmelt;


        #region Config
        public class Configuration
        {
            [JsonProperty("Configure oven capacity", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, int> OvenCapacity = new Dictionary<string, int>();

            [JsonProperty("Show oven toggle UI")]
            public bool ShowUI = true;

            [JsonProperty("UI Button Toggle Min Position")]
            public string UIToggleBtnPosMin = "0.65 0.07";

            [JsonProperty("UI Button Toggle Max Position")]
            public string UIToggleBtnPosMax = "0.73 0.12";

            [JsonProperty("UI Button Toggle Font Size")]
            public int UIToggleBtnFontSize = 17;

            [JsonProperty("Configure cookable items", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, ModCookable> _modCookables = new Dictionary<string, ModCookable>();

            [JsonProperty("Configure burnable items", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, ModBurnable> _modBurnables = new Dictionary<string, ModBurnable>();

            [JsonProperty("Custom Capacity (Set custom capacities per furnace via permission-name : capacities)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, Dictionary<string, int>> _customCapacity = new Dictionary<string, Dictionary<string, int>>() { { "customperm1", new Dictionary<string, int>() } };
            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);
        }

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

            }, this);
        }

        #endregion Config
        public class ModCookable
        {
            public float cooktime;
            public int amountToBecome;

            public ModCookable()
            {
                cooktime = 5;
                amountToBecome = 1;
            }
        }

        public class ModBurnable
        {
            public int byproductAmount;
            public float byproductChance;
            public float fuelAmount;

            public ModBurnable()
            {
                byproductAmount = 1;
                byproductChance = 1;
                fuelAmount = 20;
            }
        }


        private Dictionary<string, ModCookable> _defaultModCookables = new Dictionary<string, ModCookable>();

        private Dictionary<string, ModBurnable> _defaultModBurnables = new Dictionary<string, ModBurnable>();

        private static HashSet<int> _burnableItems;
        #region Init

        private void Init()
        {
            _OgFurnace = this;
            _burnableItems = new HashSet<int>();
            foreach (var prefab in GameManifest.Current.entities)
            {
                BaseOven oven = GameManager.server.FindPrefab(prefab.ToLower())?.GetComponent<BaseOven>();
                if (oven == null)
                    continue;
                if (config.OvenCapacity.ContainsKey(oven.ShortPrefabName))
                    continue;

                config.OvenCapacity.Add(oven.ShortPrefabName, oven.inventorySlots);
            }

            foreach (var perm in config._customCapacity)
            {
                permission.RegisterPermission($"ogfurnace.{perm.Key}", this);
                foreach (var ovenCap in config.OvenCapacity)
                {
                    if (perm.Value.ContainsKey(ovenCap.Key)) continue;
                    perm.Value.Add(ovenCap.Key, ovenCap.Value);
                }
            }

            foreach (ItemDefinition def in ItemManager.GetItemDefinitions())
            {
                ItemModBurnable fuel = def?.GetComponent<ItemModBurnable>();
                if (fuel != null)
                {
                    _burnableItems.Add(def.itemid);
                    ModBurnable modBurnable;
                    if (config._modBurnables.TryGetValue(def.shortname, out modBurnable))
                    {
                        fuel.byproductAmount = modBurnable.byproductAmount;
                        fuel.fuelAmount = modBurnable.fuelAmount;
                        fuel.byproductChance = modBurnable.byproductChance;
                    }
                    else
                    {
                        config._modBurnables.Add(def.shortname, new ModBurnable { byproductAmount = fuel.byproductAmount, byproductChance = fuel.byproductChance, fuelAmount = fuel.fuelAmount });
                    }
                    if (!_defaultModBurnables.ContainsKey(def.shortname))
                        _defaultModBurnables.Add(def.shortname, new ModBurnable { byproductAmount = fuel.byproductAmount, byproductChance = fuel.byproductChance, fuelAmount = fuel.fuelAmount });
                }
                ItemModCookable cookable = def?.GetComponent<ItemModCookable>();
                if (cookable != null)
                {
                    ModCookable modCookable;
                    if (config._modCookables.TryGetValue(def.shortname, out modCookable))
                    {
                        cookable.amountOfBecome = modCookable.amountToBecome;
                        cookable.cookTime = modCookable.cooktime;
                    }
                    else
                    {
                        config._modCookables.Add(def.shortname, new ModCookable { cooktime = cookable.cookTime, amountToBecome = cookable.amountOfBecome });
                    }
                    if (!_defaultModCookables.ContainsKey(def.shortname))
                        _defaultModCookables.Add(def.shortname, new ModCookable { cooktime = cookable.cookTime, amountToBecome = cookable.amountOfBecome });
                }
            }

            SaveConfig();
            AddLocalizedCommand(nameof(OvenToggleCMD));
            _UIButtonOn = CreateSplitterUI("On");
            _UIButtonOff = CreateSplitterUI("Off");
        }

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

            foreach (BaseOvenComponent baseOvenComponent in UnityEngine.Object.FindObjectsOfType<BaseOvenComponent>()) UnityEngine.Object.Destroy(baseOvenComponent);

            //Set cooking to default values
            foreach (ItemDefinition def in ItemManager.GetItemDefinitions())
            {
                ItemModBurnable fuel = def?.GetComponent<ItemModBurnable>();
                if (fuel != null)
                {
                    ModBurnable modBurnable;
                    if (_defaultModBurnables.TryGetValue(def.shortname, out modBurnable))
                    {
                        fuel.byproductAmount = modBurnable.byproductAmount;
                        fuel.fuelAmount = modBurnable.fuelAmount;
                        fuel.byproductChance = modBurnable.byproductChance;
                    }
                }
                ItemModCookable cookable = def?.GetComponent<ItemModCookable>();
                if (cookable != null)
                {
                    ModCookable modCookable;
                    if (_defaultModCookables.TryGetValue(def.shortname, out modCookable))
                    {
                        cookable.amountOfBecome = modCookable.amountToBecome;
                        cookable.cookTime = modCookable.cooktime;
                    }
                }
            }
        }

        #endregion Init

        #region Hooks

        private object CanLootEntity(BasePlayer player, BaseOven oven)
        {
            BaseOvenComponent baseOvenComponent = null;
            if (oven.TryGetComponent<BaseOvenComponent>(out baseOvenComponent))
            {
                if (baseOvenComponent.looter == player)
                    return null;
            }
            StartLooting(player, oven);
            return false;
        }

        object OnOvenToggle(BaseOven oven, BasePlayer player)
        {
            BaseOvenComponent baseOvenComponent;
            if (!oven.TryGetComponent<BaseOvenComponent>(out baseOvenComponent))
            {
                baseOvenComponent = oven.gameObject.AddComponent<BaseOvenComponent>();
            }

            if (QuickSmelt != null || FurnaceLevels != null || PowerSmelt != null) return null;
            baseOvenComponent.ToggleOven();
            return true;
        }

        void OnLootEntityEnd(BasePlayer player, BaseOven oven)
        {
            CuiHelper.DestroyUi(player, "OvenToggleUI");
            BaseOvenComponent baseOvenComponent;
            if (oven.TryGetComponent<BaseOvenComponent>(out baseOvenComponent))
            {
                baseOvenComponent.looter = null;
            }
        }

        void OnEntitySpawned(BaseOven oven)
        {
            if (oven.OwnerID == 0) return;
            foreach (var perm in config._customCapacity)
            {
                if (HasPerm(oven.OwnerID.ToString(), $"ogfurnace.{perm.Key}"))
                {
                    int newovencapacity = 0;
                    if (!perm.Value.TryGetValue(oven.ShortPrefabName, out newovencapacity)) continue;
                    if (newovencapacity > oven.inventory.capacity)
                    {
                        oven.inventory.capacity = newovencapacity;
                    }
                }
            }

        }

        #endregion Hooks

        #region UI
        CuiElementContainer _UIButtonOn = null;
        CuiElementContainer _UIButtonOff = null;
        CuiElementContainer CreateSplitterUI(string Toggle)
        {
            string btncolor = "0.55 0.1 0.1 1";
            string txtcolor = "1.0 1.0 1.0 0.3";
            if (Toggle == "On")
            {
                btncolor = "0.3 0.4 0.1 1";
                txtcolor = "1.0 1.0 1.0 0.3";
            }
            CuiElementContainer elements = new CuiElementContainer();
            string panel = elements.Add(new CuiPanel
            {
                Image = { Color = "0.5 0.5 0.5 0.0" },
                RectTransform = { AnchorMin = config.UIToggleBtnPosMin, AnchorMax = config.UIToggleBtnPosMax }
            }, "Hud.Menu", "OvenToggleUI");
            elements.Add(new CuiButton
            {
                Button = { Command = "OvenToggleCMD", Color = btncolor },
                Text = { Text = "Turn " + Toggle, FontSize = config.UIToggleBtnFontSize, Align = TextAnchor.MiddleCenter, Color = txtcolor },
                RectTransform = { AnchorMin = "0.00 0.00", AnchorMax = "1.0 1.0" }
            }, panel);

            return elements;
        }

        #endregion UI

        #region COMMANDS
        private void OvenToggleCMD(IPlayer iplayer, string command, string[] args)
        {
            BasePlayer player = (BasePlayer)iplayer.Object;
            BaseOven oven = (player.inventory?.loot?.entitySource ?? null) as BaseOven;
            if (oven == null) return;
            BaseOvenComponent baseOvenComponent;
            if (!oven.TryGetComponent<BaseOvenComponent>(out baseOvenComponent))
            {
                baseOvenComponent = oven.gameObject.AddComponent<BaseOvenComponent>();
            }

            if (QuickSmelt != null || FurnaceLevels != null || PowerSmelt != null)
            {
                if (oven.HasFlag(BaseEntity.Flags.On))
                {
                    oven.StopCooking();
                }
                else
                {
                    oven.StartCooking();
                }
                return;
            }
            baseOvenComponent.ToggleOven();
        }

        #endregion COMMANDS

        #region Methods

        private void StartLooting(BasePlayer player, BaseOven oven)
        {
            string panel = "generic_resizable";
            if (config.OvenCapacity.TryGetValue(oven.ShortPrefabName, out int ovenCapacity))
            {
                oven.inventory.capacity = ovenCapacity;
                if (ovenCapacity == 1)
                    panel = oven.panelName;
            }
            BaseOvenComponent baseOvenComponent;
            if (!oven.TryGetComponent<BaseOvenComponent>(out baseOvenComponent))
            {
                baseOvenComponent = oven.gameObject.AddComponent<BaseOvenComponent>();
                baseOvenComponent.oginputSlotIndex = oven._inputSlotIndex;
                baseOvenComponent.oginputSlots = oven.inputSlots;
                baseOvenComponent.ogoutputSlots = oven.outputSlots;
                baseOvenComponent.ogoutputSlotIndex = oven._outputSlotIndex;
                baseOvenComponent.ogfuelslots = oven.fuelSlots;
            }
            baseOvenComponent.looter = player;

            oven.inputSlots = oven.inventory.capacity;
            oven.outputSlots = oven.inventory.capacity;
            oven.fuelSlots = oven.inventory.capacity;

            oven._inputSlotIndex = 0;
            oven._outputSlotIndex = 0;

            oven.SendAsSnapshot(player.Connection);
            player.inventory.loot.entitySource = oven;
            player.inventory.loot.AddContainer(oven.inventory);
            player.inventory.loot.MarkDirty();
            player.inventory.loot.SendImmediate();
            player.ClientRPC<string>(RpcTarget.Player("RPC_OpenLootPanel", player), panel);
            baseOvenComponent.UpdateLooterUI();

            Interface.CallHook("OnLootEntity", player, oven);
        }
        #endregion Methods

        #region BaseOven Behaviour
        public class BaseOvenComponent : FacepunchBehaviour
        {
            private BaseOven baseOven;
            private ItemContainer inventory;
            public BasePlayer looter = null;
            public int oginputSlots;
            public int ogoutputSlots;
            public int ogfuelslots;
            public int ogoutputSlotIndex;
            public int oginputSlotIndex;

            private void Awake()
            {
                baseOven = GetComponent<BaseOven>();
                inventory = baseOven.inventory;
                inventory.onItemAddedRemoved = new Action<Item, bool>(OnItemAddedOrRemoved);
                inventory.canAcceptItem = new Func<Item, int, bool>(CanAcceptItem);
            }

            private bool CanAcceptItem(Item item, int targetPos)
            {
                if (inventory.availableSlots != null && inventory.availableSlots.Count > 0)
                {
                    if ((int)item.info.occupySlots == 0 || item.info.occupySlots == ItemSlot.None)
                    {
                        return false;
                    }

                    int[] numArray = new int[32];
                    foreach (ItemSlot availableSlot in inventory.availableSlots)
                    {
                        numArray[(int)Mathf.Log((float)availableSlot, 2f)]++;
                    }

                    foreach (Item item1 in inventory.itemList)
                    {
                        for (int i = 0; i < 32; i++)
                        {
                            if (((int)item1.info.occupySlots & 1 << (i & 31)) != 0)
                            {
                                numArray[i]--;
                            }
                        }
                    }

                    for (int j = 0; j < 32; j++)
                    {
                        if (((int)item.info.occupySlots & 1 << (j & 31)) != 0 && numArray[j] <= 0)
                        {
                            return false;
                        }
                    }
                }

                object obj = Interface.CallHook("CanAcceptItem", this, item, targetPos);
                if (!(obj is ItemContainer.CanAcceptResult))
                {
                    return true;
                }

                if (obj != null)
                {
                    return false;
                }

                return true;
            }

            #region Commands
            public void StartCooking()
            {
                if (FindBurnable() == null)
                {
                    return;
                }
                inventory.temperature = baseOven.cookingTemperature;
                UpdateAttachmentTemperature();
                InvokeRepeating(StartCook, 0.5f, 0.5f);
                baseOven.SetFlag(BaseEntity.Flags.On, true, false, true);
                UpdateLooterUI();
            }
            public void StopCooking()
            {
                UpdateAttachmentTemperature();
                if (baseOven.inventory != null)
                {
                    baseOven.inventory.temperature = 15f;
                    foreach (Item item in inventory.itemList)
                    {
                        item.SetFlag(Item.Flag.Cooking, false);
                        item.SetFlag(Item.Flag.OnFire, false);
                        item.MarkDirty();
                    }
                }
                CancelInvoke(StartCook);
                baseOven.SetFlag(BaseEntity.Flags.On, false, false, true);

                UpdateLooterUI();
            }

            #endregion Commands

            #region Cooking Methods
            private void StartCook()
            {
                Item item = FindBurnable();
                if (item == null)
                {
                    StopCooking();
                    return;
                }

                BaseEntity slot = baseOven.GetSlot(BaseEntity.Slot.FireMod);
                if (slot)
                {
                    slot.SendMessage("Cook", 0.5f, SendMessageOptions.DontRequireReceiver);
                }

                ItemModBurnable component = item.info.GetComponent<ItemModBurnable>();
                Item item1 = item;
                item1.fuel = item1.fuel - 0.5f * (baseOven.cookingTemperature / 200f);
                if (!item.HasFlag(Item.Flag.OnFire))
                {
                    item.SetFlag(Item.Flag.OnFire, true);
                    item.MarkDirty();
                }

                for (int i = 0; i < inventory.capacity; i++)
                {
                    var cookable = inventory.GetSlot(i);
                    if (cookable == null) continue;

                    if (cookable.info == baseOven.fuelType) continue;
                    ItemModCookable itemModCookable = cookable.info.GetComponent<ItemModCookable>();
                    if (itemModCookable == null) continue;

                    if (inventory.temperature <= (float)itemModCookable.lowTemp)
                        continue;
                    if (inventory.temperature > (float)itemModCookable.highTemp)
                        continue;

                    if (!cookable.HasFlag(Item.Flag.Cooking))
                    {
                        cookable.SetFlag(Item.Flag.Cooking, true);
                        cookable.MarkDirty();
                        StartCoroutine(CookItem(cookable, itemModCookable));
                    }
                }

                if (item.fuel <= 0f)
                {
                    ConsumeFuel(item, component);
                }
            }


            private void UpdateAttachmentTemperature()
            {
                BaseEntity slot = baseOven.GetSlot(BaseEntity.Slot.FireMod);
                if (slot)
                {
                    slot.SendMessage("ParentTemperatureUpdate", inventory.temperature, SendMessageOptions.DontRequireReceiver);
                }
            }

            private void ConsumeFuel(Item fuel, ItemModBurnable burnable)
            {
                if (baseOven.allowByproductCreation && burnable.byproductItem != null && UnityEngine.Random.Range(0f, 1f) > burnable.byproductChance)
                {
                    Item item = ItemManager.Create(burnable.byproductItem, burnable.byproductAmount, (ulong)0);
                    if (!item.MoveToContainer(inventory, -1, true))
                    {
                        //oven full
                        StopCooking();
                        item.Drop(inventory.dropPosition, inventory.dropVelocity, new Quaternion());
                    }
                }
                if (fuel.amount <= 1)
                {
                    fuel.Remove(0f);
                    return;
                }
                fuel.amount--;
                fuel.fuel = burnable.fuelAmount;
                fuel.MarkDirty();
            }

            #endregion Cooking Methods

            #region Helpers

            private void OnItemAddedOrRemoved(Item item, bool bAdded)
            {
                if (item != null)
                {
                    item.SetFlag(Item.Flag.Cooking, false);
                    item.SetFlag(Item.Flag.OnFire, false);
                    item.MarkDirty();
                }
            }

            private IEnumerator CookItem(Item item, ItemModCookable itemMod)
            {
                yield return CoroutineEx.waitForSeconds(itemMod.cookTime);
                if (!item.HasFlag(Item.Flag.Cooking)) yield break;

                if (item.amount <= 1)
                {
                    item.Remove(0f);
                }
                else
                {
                    item.amount--;
                    item.MarkDirty();
                }

                int num = item.position;

                if (itemMod.becomeOnCooked == null || item.amount < 1) yield break;

                Item item1 = ItemManager.Create(itemMod.becomeOnCooked, itemMod.amountOfBecome, (ulong)0);
                if (item1 != null && !item1.MoveToContainer(item.parent, num, true) &&
                    !item1.MoveToContainer(item.parent, -1, true))
                {
                    item1.Drop(item.parent.dropPosition, item.parent.dropVelocity, new Quaternion());
                    if (item.parent.entityOwner)
                    {
                        BaseOven component = item.parent.entityOwner.GetComponent<BaseOven>();
                        if (component != null)
                        {
                            StopCooking();
                        }
                    }
                }
                item.SetFlag(Item.Flag.Cooking, false);
            }

            private Item FindBurnable()
            {
                if (inventory == null)
                {
                    return null;
                }

                foreach (Item current in inventory.itemList)
                {
                    if ( !_burnableItems.Contains(current.info.itemid) || (baseOven.fuelType != null && current.info != baseOven.fuelType))
                    {
                        continue;
                    }
                    return current;
                }
                return null;
            }


            public void ToggleOven()
            {
                if (baseOven.HasFlag(BaseEntity.Flags.On))
                {
                    StopCooking();
                }
                else
                {
                    StartCooking();
                }
            }

            public void UpdateLooterUI()
            {
                if (!_OgFurnace.config.ShowUI || looter == null) return;
                CuiHelper.DestroyUi(looter, "OvenToggleUI");
                if (baseOven.HasFlag(BaseEntity.Flags.On))
                {
                    CuiHelper.AddUi(looter, _OgFurnace._UIButtonOff);
                }
                else
                {
                    CuiHelper.AddUi(looter, _OgFurnace._UIButtonOn);
                }
            }
            #endregion Helpers

            void OnDestroy()
            {
                CancelInvoke(StartCook);
                baseOven.inputSlots = oginputSlots;
                baseOven.fuelSlots = ogfuelslots;
                baseOven.outputSlots = ogoutputSlots;
                baseOven._inputSlotIndex = oginputSlotIndex;
                baseOven._outputSlotIndex = ogoutputSlotIndex;

            }
        }
        #endregion BaseOven Behaviour

        #region Helpers
        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 оценок
Сверху