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

FREE FurnaceSorter : 1.3.4 1.3.4

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

namespace Oxide.Plugins
{
    [Info("FurnaceSorter", "Sempai#3239", "1.3.4"), Description("An easy to use Furnace Sorting Tool, automatically evening out stacks")]
    class FurnaceSorter : RustPlugin
    {
        #region Fields
        private readonly Dictionary<string, Timer> _timers = new Dictionary<string, Timer>();

        private readonly Dictionary<ulong, BaseOven> _uiInfo = new Dictionary<ulong, BaseOven>();

        private readonly Hash<BaseOven, BasePlayer> entityLookup = new Hash<BaseOven, BasePlayer>();

        private UpdateInvoker _updateInvoker;

        private const string PANEL_SORTER = "PanelSorter";
        private const string PANEL_SCREEN = "PanelOnScreen";        
        private const string PERMISSION_ALLOW = "furnacesorter.allow";
        #endregion
                
        #region Oxide Hooks

        private void Loaded()
        {
            permission.RegisterPermission(PERMISSION_ALLOW, this);
            _updateInvoker = new GameObject().AddComponent<UpdateInvoker>();
        }

        protected override void LoadDefaultMessages() => lang.RegisterMessages(Messages, this);

        private void Unload()
        {
            if (_updateInvoker)
                UnityEngine.Object.Destroy(_updateInvoker);

            foreach (BasePlayer player in BasePlayer.activePlayerList)
                CloseUI(player);

            foreach (KeyValuePair<string, Timer> entry in _timers)            
                entry.Value.Destroy();            

            _timers.Clear();

            PlayerInfo.Reset();
            FurnaceInfo.Reset();

            Configuration = null;
        }

        private void OnPlayerDisconnected(BasePlayer player) => CloseUI(player);
        
        private void OnPlayerRespawned(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, PANEL_SCREEN);
            CuiHelper.DestroyUi(player, PANEL_SORTER);
        }

        private void OnLootEntity(BasePlayer player, BaseEntity entity)
        {
            if (!player || !entity) 
                return;

            if (!HasPerm(player)) 
                return;

            BaseOven oven = entity as BaseOven;
            if (oven == null || (int)oven.temperature < 2) 
                return;

            if (!_uiInfo.ContainsKey(player.userID))            
                _uiInfo.Add(player.userID, oven);            

            PlayerInfo playerInfo = PlayerInfo.Get(player);
            FurnaceInfo ovenInfo = FurnaceInfo.Get(oven);

            playerInfo.CurrentFurnaceID = ovenInfo.FurnaceID;

            ovenInfo.TimeRemaining = SmeltTimeRemaining(oven);
            ovenInfo.FuelRequired = GetFuelRequired(oven, ovenInfo.TimeRemaining);

            _uiInfo[player.userID] = oven;

            entityLookup[oven] = player;

            _updateInvoker.Invoke(oven, ()=> UpdateUICycle(oven, player));

            SorterUI(player);
        }

        private void OnPlayerLootEnd(PlayerLoot looter)
        {
            if (looter == null || looter.entitySource == null)            
                return;            

            if (!(looter.entitySource is BaseOven))            
                return;

            BaseOven oven = (looter.entitySource as BaseOven);

            if ((int)oven.temperature < 2)
                return;
            
            entityLookup.Remove(oven);

            BasePlayer player = looter._baseEntity as BasePlayer;
            if (player == null)            
                return;
            
            _updateInvoker.CancelInvoke(oven, ()=> UpdateUICycle(oven, player));

            PlayerInfo playerInfo = PlayerInfo.Get(player);
            playerInfo.CurrentFurnaceID = 0;

            if (_uiInfo.ContainsKey(player.userID))            
                _uiInfo[player.userID] = null;            

            CuiHelper.DestroyUi(player, PANEL_SORTER);
        }

        private void OnItemAddedToContainer(ItemContainer container, Item item) =>
            UpdateFurnace(container, item, true, true);

        private void OnItemRemovedFromContainer(ItemContainer container, Item item) => 
            UpdateFurnace(container, item);

        private void OnItemStacked(Item item, Item otherItem, ItemContainer container)
        {
            if (item == null || otherItem == null)
                return;
            
            if (item.parent != null && item.parent == otherItem.parent)
                return;
            
            UpdateFurnace(container, item, true, true);
        }

        private void OnItemSplit(Item item, int splitAmount)
        {
             NextTick(() =>
             {
                 if (item == null)
                     return;
                 
                 UpdateFurnace(item.parent, item);
             });
        }
        #endregion
       
        #region Functions
        private void UpdateFurnace(ItemContainer container, Item item, bool adjustFuel = false, bool sortInputSlots = false)
        {
            if (container == null)
                return;
            
            BaseOven targetOven = container.entityOwner as BaseOven;
            if (targetOven == null || targetOven.IsBurnableItem(item) || targetOven.IsOutputItem(item) || (int)targetOven.temperature < 2)            
                return;

            BasePlayer player;
            if (!entityLookup.TryGetValue(targetOven, out player))
                return;
            
            if (player == null || !HasPerm(player))
                return;
            
            PlayerInfo playerInfo = PlayerInfo.Get(player);

            if (!playerInfo.SorterEnabled)
                return;
            
            playerInfo.CurrentFurnaceID = targetOven.net.ID;

            FurnaceInfo furnaceInfo = FurnaceInfo.Get(targetOven);
            
            if (sortInputSlots)
                SortInputSlots(targetOven, item);

            furnaceInfo.TimeRemaining = SmeltTimeRemaining(targetOven);

            int fuelRequired = GetFuelRequired(targetOven, furnaceInfo.TimeRemaining);
            furnaceInfo.FuelRequired = fuelRequired;

            if (adjustFuel && playerInfo.AutoFuelEnabled)
                AdjustAutoFuel(player, targetOven, fuelRequired);

            SorterUI(player);
        }

        private void AdjustAutoFuel(BasePlayer player, BaseOven targetOven, int fuelRequired)
        {
            int fuelInOven = 0;

            for (int i = 0; i < targetOven.fuelSlots; i++)
            {
                Item slot = targetOven.inventory.GetSlot(i);
                if (slot != null && slot.info == targetOven.fuelType)
                    fuelInOven += slot.amount;
            }

            int fuelCapacity = targetOven.fuelType.stackable * targetOven.fuelSlots;

            if (fuelInOven < fuelRequired && fuelInOven < fuelCapacity)
            {
                int playerFuelAmount = player.inventory.GetAmount(targetOven.fuelType.itemid);
                int amountToMove = Mathf.Min(playerFuelAmount, fuelRequired - fuelInOven, fuelCapacity - fuelInOven);
                
                if (playerFuelAmount > 0 && amountToMove > 0)
                {
                    player.inventory.Take(null, targetOven.fuelType.itemid, amountToMove);
                    targetOven.inventory.AddItem(targetOven.fuelType, amountToMove, 0UL, ItemContainer.LimitStack.All);
                }
            }
        }

        private void SortInputSlots(BaseOven oven, Item inputItem)
        {
            List<Item> list = Facepunch.Pool.GetList<Item>();
            int totalInContainer = 0;
            int freeSlots = 0;
            
            for (int i = oven._inputSlotIndex; i < oven._inputSlotIndex + oven.inputSlots; i++)
            {
                Item item = oven.inventory.GetSlot(i);
                if (item != null)
                {
                    if (item.info == inputItem.info)
                    {
                        list.Add(item);
                        totalInContainer += item.amount;
                    }
                }
                else freeSlots++;
            }

            if (totalInContainer < oven.inputSlots)
                return;
            
            if (freeSlots > 0)
            {
                for (int i = 0; i < freeSlots; i++)
                {
                    for (int y = oven._inputSlotIndex; y < oven._inputSlotIndex + oven.inputSlots; y++)
                    {
                        Item slot = oven.inventory.GetSlot(y);
                        if (slot == null)
                        {
                            Item item = ItemManager.Create(inputItem.info, 1, 0UL);
                            
                            item.RemoveFromContainer();
                            item.RemoveFromWorld();
                            
                            item.position = y;
                            item.parent = oven.inventory;

                            oven.inventory.itemList.Add(item);
                            oven.inventory.MarkDirty();
                            
                            if (oven.inventory.onItemAddedRemoved != null)
                                oven.inventory.onItemAddedRemoved(item, true);

                            item.MarkDirty();
                            list.Add(item);
                        }
                    }
                }
            }
            
            int amountPerSlot = Mathf.CeilToInt((float)totalInContainer / (float)list.Count);
            for (int i = 0; i < list.Count; i++)
            {
                Item item = list[i];
                item.amount = Mathf.Min(amountPerSlot, totalInContainer);
                item.MarkDirty();

                totalInContainer -= item.amount;
            }
        }

        private float SmeltTimeRemaining(BaseOven oven)
        {
            float totalTime = 0;

            for (int i = oven._inputSlotIndex; i < oven._inputSlotIndex + oven.inputSlots; i++)
            {
                Item slot = oven.inventory.GetSlot(i);
                if (slot != null)
                {
                    ItemModCookable itemModCookable = slot.info.GetComponent<ItemModCookable>();
                    if (itemModCookable)
                    {
                        if (slot.cookTimeLeft < itemModCookable.cookTime)
                        {
                            totalTime += itemModCookable.cookTime * (float) (slot.amount - 1);
                            totalTime += slot.cookTimeLeft;
                        }
                        else totalTime += itemModCookable.cookTime * (float) slot.amount;
                    }
                
                }
            }

            return totalTime / (float) oven.smeltSpeed;
        }

        private int GetFuelRequired(BaseOven oven, float totalCookTime)
        {
            ItemModBurnable itemModBurnable = oven.fuelType.GetComponent<ItemModBurnable>();
            if (itemModBurnable)
            {
                int fuelAmount = Mathf.CeilToInt(totalCookTime / (itemModBurnable.fuelAmount / (oven.cookingTemperature / 200f)));
                return fuelAmount;
            }

            return Mathf.CeilToInt(totalCookTime);
        }

        private void UpdateUICycle(BaseOven targetOven, BasePlayer player)
        {
            if (!targetOven || !player)
                return;

            if (_updateInvoker.IsOpen(targetOven))
            {
                if (targetOven.IsOn())
                {
                    PlayerInfo playerInfo = PlayerInfo.Get(player);

                    if (playerInfo.SorterEnabled)
                    {
                        FurnaceInfo furnaceInfo = FurnaceInfo.Get(targetOven);

                        furnaceInfo.TimeRemaining = SmeltTimeRemaining(targetOven);
                        furnaceInfo.FuelRequired = GetFuelRequired(targetOven, furnaceInfo.TimeRemaining);

                        SorterUI(player);
                    }
                }

                _updateInvoker.Invoke(targetOven, () => UpdateUICycle(targetOven, player));
            }
        }
        
        private class UpdateInvoker : MonoBehaviour
        {
            private readonly HashSet<BaseOven> openOvens = new HashSet<BaseOven>();

            public void Invoke(BaseOven baseOven, Action action)
            {
                openOvens.Add(baseOven);
                InvokeHandler.Invoke(this, action, 1f);
            }

            public void CancelInvoke(BaseOven baseOven, Action action)
            {
                openOvens.Remove(baseOven);
                InvokeHandler.CancelInvoke(this, action);
            }

            public bool IsOpen(BaseOven baseOven) => openOvens.Contains(baseOven);
        }
        #endregion

        #region Helpers
        private void SendMessage(BasePlayer player, string key, params object[] args)
        {
            string message = GetMessage(key, player, args);
            SendReply(player, $"<color=orange>{GetMessage("Title", player)}</color><color=#A9A9A9>{message}</color>");
        }

        private bool HasPerm(BasePlayer player, string perm = PERMISSION_ALLOW) => (player.IsAdmin || permission.UserHasPermission(player.UserIDString, perm));
        #endregion

        #region UI Commands
        [ConsoleCommand("UI_ToggleSorter")]
        private void UIToggleSorterConsoleCommand(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPerm(player) || arg.Args.Length < 1)
                return;

            PlayerInfo playerInfo = PlayerInfo.Get(player);

            string option = arg.Args[0].ToLower();

            if (option == "sorter")
            {
                if (!playerInfo.SorterEnabled)
                {
                    playerInfo.SorterEnabled = true;
                    playerInfo.AutoFuelEnabled = true;

                    //OnScreen(player, "FurnaceSorterEnabled");
                    SorterUI(player);
                    return;
                }

                playerInfo.SorterEnabled = false;

                //OnScreen(player, "FurnaceSorterDisabled");
                SorterUI(player);
                return;
            }

            if (option == "autofuel")
            {
                playerInfo.AutoFuelEnabled = !playerInfo.AutoFuelEnabled;

                SorterUI(player);
                return;
            }

            //if (option == "stack")
            //{
            //    if (arg.Args.Length < 2)                
            //        return;                

            //    string stackOption = arg.Args[1].ToLower();

            //    if (stackOption == "increase")
            //    {
            //        if (playerInfo.ReservedCount >= 8)
            //            return;                    

            //        playerInfo.ReservedCount++;

            //        SorterUI(player);
            //        return;
            //    }

            //    if (stackOption == "decrease")
            //    {
            //        if (playerInfo.ReservedCount == 0)                    
            //            return;                    

            //        playerInfo.ReservedCount--;

            //        SorterUI(player);
            //        return;
            //    }
            //}
        }

        #endregion

        #region UI Helper
        internal class UI
        {
            internal static CuiElementContainer Container(string panelName, string color, string aMin, string aMax, bool cursor = false)
            {
                return new CuiElementContainer()
                {
                    {
                        new CuiPanel
                        {
                            Image = { Color = color },
                            RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
                            CursorEnabled = cursor
                        },
                        new CuiElement().Parent = "Overlay",
                        panelName
                    }
                };
            }

            internal static void Button(CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, string command, float fadeIn = 0f, TextAnchor align = TextAnchor.MiddleCenter)
            {
                container.Add(new CuiButton
                {
                    Button = { Color = color, Command = command, FadeIn = fadeIn },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
                    Text = { Text = text, FontSize = size, Align = align }
                }, panel);
            }

            internal static void Text(CuiElementContainer element, string panel, string colorText, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter)
            {
                element.Add(new CuiElement
                {
                    Parent = panel,
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Color = colorText,
                            FontSize = size,
                            Align = align,
                            Text = text
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = aMin,
                            AnchorMax = aMax
                        }
                    }
                });
            }

            internal static void Outline(ref CuiElementContainer element, string panel, string colorText, string colorOutline, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter)
            {
                element.Add(new CuiElement
                {
                    Parent = panel,
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Color = colorText,
                            FontSize = size,
                            Align = align,
                            Text = text
                        },
                        new CuiOutlineComponent
                        {
                            Distance = "1 1",
                            Color = colorOutline
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = aMin,
                            AnchorMax = aMax
                        }
                    }
                });
            }
        }
        #endregion

        #region UI Creation
        private void SorterUI(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, PANEL_SORTER);

            CuiElementContainer element = UI.Container(PANEL_SORTER, "1 0 0 0.0", "0.651 0.020", "0.8141 0.140");

            PlayerInfo playerInfo = PlayerInfo.Get(player);

            string enabledColour = playerInfo.SorterEnabled ? "0.439 0.509 0.294 1.0" : "0.584 0.29 0.211 1.0";
            string enabledText = playerInfo.SorterEnabled ? "SorterEnabled" : "SorterDisabled";

            UI.Button(element, PANEL_SORTER, enabledColour, GetMessage(enabledText, player), 12, "0 0.75", "0.495 1", "UI_ToggleSorter sorter");

            if (playerInfo.SorterEnabled)
            {
                bool autoFuelEnabled = playerInfo.AutoFuelEnabled;

                string autoFuelEnabledText = autoFuelEnabled ? "AutoFuelEnabled" : "AutoFuelDisabled";

                UI.Button(element, PANEL_SORTER, enabledColour, GetMessage(autoFuelEnabledText, player), 12, "0.505 0.75", "1 1", "UI_ToggleSorter autofuel", 0.0f);
                
                FurnaceInfo furnaceInfo = FurnaceInfo.FindByID(playerInfo.CurrentFurnaceID);
                if (furnaceInfo != null)
                {
                    string rateKey = furnaceInfo.Temperature == BaseOven.TemperatureType.Smelting ? "SmeltRate" :
                                     furnaceInfo.Temperature == BaseOven.TemperatureType.Cooking ? "CookRate" : 
                                     furnaceInfo.Temperature == BaseOven.TemperatureType.Fractioning ? "RefineRate" :  string.Empty;

                    if (string.IsNullOrEmpty(rateKey))
                        return;
                    
                    UI.Text(element, PANEL_SORTER, "1 1 1 1", GetMessage(rateKey, player, furnaceInfo.SmeltRate), 12, "0 0", "1.0 0.25", TextAnchor.MiddleLeft);
                   
                    if (furnaceInfo.TimeRemaining > 0)
                    {
                        string timeMessage = string.Empty;
                        TimeSpan timeSpan = TimeSpan.FromSeconds(furnaceInfo.TimeRemaining);
                        if (timeSpan.Hours > 0)
                            timeMessage = string.Format("~ {0:D2}h:{1:D2}m:{2:D2}s", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds);
                        else timeMessage = string.Format("~ {0:D2}m:{1:D2}s", timeSpan.Minutes, timeSpan.Seconds);

                        UI.Text(element, PANEL_SORTER, "1 1 1 1", GetMessage("TimeRemaining", player, timeMessage), 12, "0 0.5", "1.0 0.75", TextAnchor.MiddleLeft);
                    }

                    if (furnaceInfo.FuelRequired > 0)
                        UI.Text(element, PANEL_SORTER, "1 1 1 1", GetMessage("FuelRequired", player, string.Format("~ {0:n0}", furnaceInfo.FuelRequired)), 12, "0 0.25", "1.0 0.5", TextAnchor.MiddleLeft);
                }

                //UI.Button(element, PANEL_SORTER, "1 0 0 0.3", "-", 14, "0 0.025", "0.15 0.225", "UI_ToggleSorter stack decrease", 0f);

                //UI.Text(element, PANEL_SORTER, "1 1 1 1", $"Reserved Slots : {playerInfo.ReservedCount}", 12, "0.15 0", "0.85 0.25", TextAnchor.MiddleCenter);

                //UI.Button(element, PANEL_SORTER, "0 1 0 0.3", "+", 14, "0.85 0.025", "1 0.225", "UI_ToggleSorter stack increase", 0f);
            }

            CuiHelper.AddUi(player, element);
        }

        private void OnScreen(BasePlayer player, string msg)
        {
            if (_timers.ContainsKey(player.userID.ToString()))
            {
                _timers[player.userID.ToString()].Destroy();
                _timers.Remove(player.userID.ToString());
            }

            CuiElementContainer element = UI.Container(PANEL_SCREEN, "0.0 0.0 0.0 0.0", "0.3 0.5", "0.7 0.8");
            UI.Outline(ref element, PANEL_SCREEN, string.Empty, "0 0 0 1", GetMessage(msg, player), 32, "0.0 0.0", "1.0 1.0");

            CuiHelper.DestroyUi(player, PANEL_SCREEN);
            CuiHelper.AddUi(player, element);

            _timers.Add(player.userID.ToString(), timer.Once(4, () => CuiHelper.DestroyUi(player, PANEL_SCREEN)));
        }

        private void CloseUI(BasePlayer player)
        {
            if (player == null)
                return;

            if (_uiInfo.ContainsKey(player.userID))
                _uiInfo.Remove(player.userID);

            if (_timers.ContainsKey(player.userID.ToString()))
            {
                _timers[player.userID.ToString()].Destroy();
                _timers.Remove(player.userID.ToString());
            }

            PlayerInfo playerInfo = PlayerInfo.Get(player);

            //playerInfo.SorterEnabled = false;

            CuiHelper.DestroyUi(player, PANEL_SCREEN);

            CuiHelper.DestroyUi(player, PANEL_SORTER);
        }
        #endregion

        #region Config
        private static ConfigData Configuration;

        private class ConfigData
        {
            public bool EnabledByDefault = false;
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            Configuration = Config.ReadObject<ConfigData>();
            Config.WriteObject(Configuration, true);
        }

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

        protected override void SaveConfig() => Config.WriteObject(Configuration, true);
        #endregion

        #region Data
        private class PlayerInfo
        {
            public BasePlayer Player { get; set; }

            public bool SorterEnabled { get; set; }

            public bool AutoFuelEnabled { get; set; }

            //public int ReservedCount { get; set; }

            public uint CurrentFurnaceID { get; set; }


            private static Hash<ulong, PlayerInfo> _playerInfos = new Hash<ulong, PlayerInfo>();

            public PlayerInfo(BasePlayer player)
            {
                this.Player = player;
                this.SorterEnabled = Configuration.EnabledByDefault;
                this.AutoFuelEnabled = true;
                //this.ReservedCount = 3;
            }

            public static PlayerInfo Get(BasePlayer player)
            {
                if (player == null)
                    return null;

                PlayerInfo playerInfo;
                if (!_playerInfos.TryGetValue(player.userID, out playerInfo))
                    playerInfo = _playerInfos[player.userID] = new PlayerInfo(player);

                return playerInfo;
            }

            public static void Reset() => _playerInfos.Clear();
        }

        private class FurnaceInfo
        {
            public uint FurnaceID { get; set; }

            public float TimeRemaining { get; set; }

            public int FuelRequired { get; set; }
            
            public float SmeltRate { get; set; }
            
            public BaseOven.TemperatureType Temperature { get; set; }


            private static Hash<uint, FurnaceInfo> _furnaceInfos = new Hash<uint, FurnaceInfo>();

            public FurnaceInfo(BaseOven oven)
            {
                this.FurnaceID = oven.net.ID;
                this.TimeRemaining = 0f;
                this.FuelRequired = 0;
                this.SmeltRate = oven.smeltSpeed;
                this.Temperature = oven.temperature;
            }

            public static FurnaceInfo Get(BaseOven oven)
            {
                if (oven == null)                
                    return null;

                FurnaceInfo furnaceInfo;
                if (!_furnaceInfos.TryGetValue(oven.net.ID, out furnaceInfo))
                    furnaceInfo = _furnaceInfos[oven.net.ID] = new FurnaceInfo(oven);

                return furnaceInfo;
            }

            public static FurnaceInfo FindByID(uint id)
            {
                FurnaceInfo furnaceInfo;
                if (!_furnaceInfos.TryGetValue(id, out furnaceInfo))
                    return null;

                return furnaceInfo;
            }

            public static void Reset() => _furnaceInfos.Clear();
        }
        #endregion


        #region Localization
        private string GetMessage(string key, BasePlayer player = null, params object[] args) => string.Format(lang.GetMessage(key, this, player?.UserIDString), args);

        private Dictionary<string, string> Messages = new Dictionary<string, string>()
        {
            { "Title", "FurnaceSorter: " },
            { "NoPerm","You do not have permission to use this command" },

            { "FurnaceSorterDisabled", "FurnaceSorter is now disabled." },
            { "FurnaceSorterEnabled", "FurnaceSorter is now enabled." },

            { "SorterEnabled", "Sorter Enabled" },
            { "SorterDisabled", "Sorter Disabled" },
            { "AutoFuelEnabled", "Auto-fuel Enabled" },
            { "AutoFuelDisabled", "Auto-fuel Disabled" },
            
            { "OptimizationUnavailable", "You can not use the Optimizer while the furnace is on!" },
            { "NothingToOptimize", "There is nothing in the furnace to optimize.Optimization Failed!" },
            { "NoWood", "The furnace does not appear to have wood.Optimization Failed!" },
            { "NoAcceptableItems", "The furnace does not appear to have any valid items to optimize wood against.Optimization Failed!" },
            { "WoodRatioGood", "The wood to acceptable item ratio is correct.No Optimization Required!" },
            { "WoodNeeded", "Optimizing found you are short {0} wood" },
            { "ExtraWoodGiven", "Optimizing found you have {0} extra wood.This wood has been placed in your inventory!" },
            { "InventoryFull", "Your furnace has {0} extra wood but it will not fit in your inventory.Optimization Failed!" },
            { "FurnaceOptimized", "Your furnace has been optimized!" },
            { "TimeRemaining", "Time Remaining: {0}" },
            { "FuelRequired", "Total Fuel Required: {0}" },
            { "SmeltRate", "Smelt Rate: {0}" },
            { "CookRate", "Cook Rate: {0}" },
            { "RefineRate", "Refine Rate: {0}"}
        };
        #endregion
    }
}

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

Другие ресурсы пользователя 15FPS

Сверху