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

FREE FurnaceUpgrades : 2.5.3 2.5.3

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6

/*
*  <----- End-User License Agreement ----->
*  Copyright © 2024 Iftebinjan
*  Devoloper: Iftebinjan (Contact: https://discord.gg/HFaGs8YwsH)
*  
*  You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of This Software without the Developer’s consent
*  
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
*  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.* 
*/
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("FurnaceUpgrades", "ifte", "2.5.3")]
    [Description("Upgrade your furnaces and improve smelting!")]
    internal class FurnaceUpgrades : RustPlugin {
        /*------------------------------------
         *
         *          FurnaceUpgrades by Ifte
         *            Original Author: Yun
         *    Support: https://discord.gg/cCWadjcapr
         *    Fiverr: https://www.fiverr.com/s/e2pkYY
         *            Eror404 not found
         *
         -------------------------------------*/
        /* Version: 2.5.3
         * - Fixed Console Spam from StackModifer(Codefling + Umod)
         * - Added On new wipe its going to reset existing furnaces data
        */
        /* Version: 2.5.2
         * - Fixed for old update.*/
        /* Version: 2.5.1
         * - Fixed oven running after water gunned
        */
        /* Version: 2.5.0
         * - Fixed item not spliting on ovens
         * - Fixed less fuel needed on higher smelting items
         * - Adjusted Fuel Speed Multiplier and Smelting speed for vanilla
         * - Fixed Furnace timings for vanilla
         * - Fixed Notification
         * - Fixed Stacks issues (Solution on Description)
        */
#region Fields
        [PluginReference]
        private Plugin Economics, ServerRewards, Toastify, Notify, ImageLibrary, StackModifier;
        private static FurnaceUpgrades _instance;
        private OvenController _controller;
        private const string USE_PERMISSION = "FurnaceUpgrades.use";
        private const string AUTO_FUEL_PERMISSION = "FurnaceUpgrades.autofuel";
        private const string AUTO_SPLIT_PERMISSION = "FurnaceUpgrades.autosplit";
        private readonly bool doDebug = false;
        private readonly string[] _conflictPlugins = new string[] {
            "StacksExtended", "StackModifier", "StackSizeController"
        }
        ;
        private readonly Dictionary<string, string> _ovensPrefab = new Dictionary<string, string>() {
            {
                "furnace", "assets/prefabs/deployable/furnace/furnace.prefab"
            }
            , {
                "furnace.large", "assets/prefabs/deployable/furnace.large/furnace.large.prefab"
            }
            , {
                "electric.furnace", "assets/prefabs/deployable/playerioents/electricfurnace/electricfurnace.deployed.prefab"
            }
            , {
                "legacyfurnace", "assets/prefabs/deployable/legacyfurnace/legacy_furnace.prefab"
            }
            , {
                "campfire", "assets/prefabs/deployable/campfire/campfire.prefab"
            }
            , {
                "bbq", "assets/prefabs/deployable/bbq/bbq.deployed.prefab"
            }
            , {
                "small.oil.refinery", "assets/prefabs/deployable/oil refinery/refinery_small_deployed.prefab"
            }
        }
        ;
        private readonly Dictionary<string, string> _images = new Dictionary<string, string>() {
            {
                "legacyfurnace_image", "https://i.ibb.co/tLxgDP0/legacyfurnace-300x300.png"
            }
        }
        ;
        private readonly Hash<ulong, BaseOven> _openModals = new Hash<ulong, BaseOven>();
        private Coroutine _setupOvensCoroutine;
        private class OvenSlot {
            public Item Item;
            public int? Position;
            public int Index;
            public int DeltaAmount;
        }
        private class OvenInfo {
            public float ETA;
            public float FuelNeeded;
        }
        private class OvenStatus {
            public float SmeltingSpeed;
            public float FuelSpeed;
            public float ResourceOutput;
            public float CharcoalMultiplier;
        }
        private class UpgradeResult {
            public UpgradeResultType Type;
            public int Cost;
            public enum UpgradeResultType {
                NotEnoughMoney, Success, MaxLevel,
            }
            public UpgradeResult(UpgradeResultType type, int cost) {
                Type = type;
                Cost = cost;
            }
        }
#region Enums
        private enum FeatureType {
            SmeltingSpeed, FuelSpeed, ResourceOutput, CharcoalMultiplier
        }
        private enum CurrencyType {
            Item, Economics, ServerRewards
        }
        private enum NotificationPlugin {
            None, Toastify, Notify
        }
#endregion
#endregion
#region Data
        private static Dictionary<ulong, FurnaceData> _furnacesData;
        private enum FurnaceDataType {
            Furnace, Item
        }
        private class FurnaceData {
            public FurnaceDataType type;
            public bool useAutoFuel = true;
            public bool useAutoSplit = true;
            public Levels levels = new Levels();
            public class Levels {
                public int smeltingSpeed;
                public int fuelSpeed;
                public int resourceOutput;
                public int charcoalMultiplier;
            }
        }
        private void LoadData() {
            try {
                _furnacesData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, FurnaceData>>(Name);
            }
            catch {
                _furnacesData = new Dictionary<ulong, FurnaceData>();
            }
            if (_furnacesData == null) _furnacesData = new Dictionary<ulong, FurnaceData>();
        }
        private void SaveData() {
            Interface.Oxide.DataFileSystem.WriteObject(Name, _furnacesData);
        }
#endregion
#region Configuration
        private static Configuration _config;
        private class UpgradeSettings {
            [JsonProperty("Smelting speed")]
            public Upgrade[] SmeltingSpeed {
                get;
                set;
            }
            [JsonProperty("Fuel speed")]
            public Upgrade[] FuelSpeed {
                get;
                set;
            }
            [JsonProperty("Resource output multiplier")]
            public Upgrade[] ResourceOutput {
                get;
                set;
            }
            [JsonProperty("Charcoal multiplier")]
            public Upgrade[] CharcoalMultiplier {
                get;
                set;
            }
            public class Upgrade {
                public int Cost {
                    get;
                    set;
                }
                public float Multiplier {
                    get;
                    set;
                }
                public Upgrade(int cost, float multiplier) {
                    Cost = cost;
                    Multiplier = multiplier;
                }
            }
        }
        private class DefaultSettings {
            [JsonProperty("Smelting speed")]
            public float SmeltingSpeed {
                get;
                set;
            }
            [JsonProperty("Fuel speed")]
            public float FuelSpeed {
                get;
                set;
            }
            [JsonProperty("Resource output multiplier")]
            public float ResourceOutput {
                get;
                set;
            }
            [JsonProperty("Charcoal multiplier")]
            public float CharcoalMultiplier {
                get;
                set;
            }
        }
        private class FeaturesSettings {
            [JsonProperty("Smelting speed multiplier")]
            public bool SmeltingSpeed {
                get;
                set;
            }
            [JsonProperty("Fuel speed")]
            public bool FuelSpeed {
                get;
                set;
            }
            [JsonProperty("Resource output multiplier")]
            public bool ResourceOutput {
                get;
                set;
            }
            [JsonProperty("Charcoal multiplier")]
            public bool CharcoalMultiplier {
                get;
                set;
            }
            [JsonProperty("Auto split cookables")]
            public bool AutoSplit {
                get;
                set;
            }
            [JsonProperty("Auto add fuel")]
            public bool AutoFuel {
                get;
                set;
            }
        }
        private class UISettings {
            [JsonProperty("Disable status panel")]
            public bool DisableStatusPanel {
                get;
                set;
            }
            [JsonProperty("Upgrade button")]
            public BasicSettings UpgradeButton {
                get;
                set;
            }
            [JsonProperty("Upgrade button on electric furnaces")]
            public BasicSettings UpgradeButtonElectricFurnace {
                get;
                set;
            }
            [JsonProperty("Status panel")]
            public BasicSettings StatusPanel {
                get;
                set;
            }
            public class BasicSettings {
                public string Anchor {
                    get;
                    set;
                }
                public string Offset {
                    get;
                    set;
                }
                [JsonProperty("Background color")]
                public string BackgroundColor {
                    get;
                    set;
                }
                [JsonProperty("Font size")]
                public int FontSize {
                    get;
                    set;
                }
            }
        }
        private class VisualSettings {
            [JsonProperty("Use chat messages")]
            public bool UseChatMessages {
                get;
                set;
            }
            [JsonProperty("Notification plugin (0 - None | 1 - Toastify | 2 - Notify)")]
            public NotificationPlugin NotificationPlugin {
                get;
                set;
            }
            [JsonProperty("Toastify notification ID")]
            public string ToastifyNotificationId {
                get;
                set;
            }
            [JsonProperty("Notify notification type")]
            public int NotifyNotificationType {
                get;
                set;
            }
            [JsonProperty("Upgrade effect (empty = disabled)")]
            public string UpgradeEffect {
                get;
                set;
            }
        }
        private class CurrencySettings {
            [JsonProperty("Currency type (0 - Scrap | 1 - Economics | 2 - Server Rewards)")]
            public CurrencyType Type {
                get;
                set;
            }
            [JsonProperty("Currency item (if the currency type is '0')")]
            public CurrencyItem Item {
                get;
                set;
            }
            public class CurrencyItem {
                [JsonProperty("Short name")]
                public string ShortName {
                    get;
                    set;
                }
                [JsonProperty("Skin ID")]
                public ulong SkinID {
                    get;
                    set;
                }
            }
        }
        private class GeneralSettings {
            [JsonProperty("Only the owner can upgrade the furnace")]
            public bool OwnerOnly {
                get;
                set;
            }
            [JsonProperty("Only teammates can upgrade the furnace")]
            public bool OnlyTeamMates {
                get;
                set;
            }
            [JsonProperty("Keep attributes when removing")]
            public bool KeepAttributes {
                get;
                set;
            }
        }
        private class Configuration {
            [JsonProperty("General Settings")]
            public GeneralSettings General {
                get;
                set;
            }
            [JsonProperty("Currency Settings")]
            public CurrencySettings Currency {
                get;
                set;
            }
            [JsonProperty("Visual Settings")]
            public VisualSettings Visual {
                get;
                set;
            }
            [JsonProperty("UI Settings")]
            public UISettings UI {
                get;
                set;
            }
            [JsonProperty("Features Settings")]
            public FeaturesSettings Features {
                get;
                set;
            }
            [JsonProperty("Default Settings")]
            public DefaultSettings Defaults {
                get;
                set;
            }
            [JsonProperty("Upgrades Settings", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, UpgradeSettings> Upgrades {
                get;
                set;
            }
            public VersionNumber Version {
                get;
                set;
            }
        }
        private Configuration GetBaseConfig() {
            UpgradeSettings upgradeSettings = new UpgradeSettings() {
                SmeltingSpeed = new UpgradeSettings.Upgrade[] {
                    new UpgradeSettings.Upgrade(100, 2f), new UpgradeSettings.Upgrade(200, 3f),
                }
                , CharcoalMultiplier = new UpgradeSettings.Upgrade[] {
                    new UpgradeSettings.Upgrade(100, 2f)
                }
                , FuelSpeed = new UpgradeSettings.Upgrade[] {
                    new UpgradeSettings.Upgrade(100, 2f)
                }
                , ResourceOutput = new UpgradeSettings.Upgrade[] {
                    new UpgradeSettings.Upgrade(100, 2f)
                }
            }
            ;
            return new Configuration() {
                General = new GeneralSettings() {
                    OwnerOnly = false, OnlyTeamMates = true, KeepAttributes = true
                }
                , Currency = new CurrencySettings() {
                    Type = CurrencyType.Item, Item = new CurrencySettings.CurrencyItem() {
                        ShortName = "scrap", SkinID = 0ul
                    }
                }
                , Visual = new VisualSettings() {
                    UseChatMessages = true, NotificationPlugin = NotificationPlugin.Toastify, ToastifyNotificationId = "success", NotifyNotificationType = 0, UpgradeEffect = "assets/bundled/prefabs/fx/build/promote_stone.prefab"
                }
                , UI = new UISettings() {
                    DisableStatusPanel = false, UpgradeButton = new UISettings.BasicSettings() {
                        Anchor = "0.5 0 0.5 0", Offset = "400 109.5 480 141.5", BackgroundColor = UIBuilder.Colors.GREEN, FontSize = 13
                    }
                    , UpgradeButtonElectricFurnace = new UISettings.BasicSettings() {
                        Anchor = "0.5 0 0.5 0", Offset = "492 354.5 572 386.5", BackgroundColor = UIBuilder.Colors.GREEN, FontSize = 13
                    }
                    , StatusPanel = new UISettings.BasicSettings() {
                        Anchor = "0.5 0 0.5 0", Offset = "193 17 420 103", BackgroundColor = "0.969 0.922 0.882 0.035", FontSize = 12
                    }
                }
                , Features = new FeaturesSettings() {
                    SmeltingSpeed = true, FuelSpeed = true, CharcoalMultiplier = true, ResourceOutput = true, AutoFuel = true, AutoSplit = true,
                }
                , Defaults = new DefaultSettings() {
                    FuelSpeed = 1f, CharcoalMultiplier = 1f, ResourceOutput = 1f, SmeltingSpeed = 1f
                }
                , Upgrades = _ovensPrefab.ToDictionary((x) => x.Key, (x) => upgradeSettings), Version = Version
            }
            ;
        }
#region Overrides
        protected override void LoadDefaultConfig() => _config = GetBaseConfig();
        protected override void LoadConfig() {
            base.LoadConfig();
            _config = Config.ReadObject<Configuration>();
            if (_config.Version < Version) UpdateConfigValues();
            Config.WriteObject(_config, true);
        }
        protected override void SaveConfig() => Config.WriteObject(_config, true);
        private void UpdateConfigValues() {
            PrintWarning("Your config file is outdated! Updating config values...");
            if (_config.Version < new VersionNumber(2, 0, 3)) {
                Configuration baseConfig = GetBaseConfig();
                _config.General.OnlyTeamMates = baseConfig.General.OnlyTeamMates;
            }
            if (_config.Version < new VersionNumber(2, 0, 40)) {
                Configuration baseconfig = GetBaseConfig();
                _config.UI.UpgradeButtonElectricFurnace = baseconfig.UI.UpgradeButtonElectricFurnace;
            }
            _config.Version = Version;
            PrintWarning("Config updated!");
        }
#endregion
#endregion
#region Localization
        private void SendNotification(BasePlayer player, string message, params object[] args) {
            if (_config.Visual.NotificationPlugin == NotificationPlugin.None) return;
            if (_config.Visual.NotificationPlugin == NotificationPlugin.Toastify) {
                if (!Toastify) return;
                Toastify.CallHook("SendToast", player, _config.Visual.ToastifyNotificationId, "UPGRADES", GetMessage(player, message, args), 3f);
            }
            else if (Notify) {
                Notify.CallHook("SendNotify", player.UserIDString, _config.Visual.NotifyNotificationType, GetMessage(player, message, args));
            }
        }
        private void SendMessage(BasePlayer player, string message, params object[] args) {
            if (_config.Visual.UseChatMessages) player.ChatMessage($"{GetMessage(player, "Chat.Prefix")}: {GetMessage(player, message, args)}");
            SendNotification(player, message, args);
        }
        private string GetMessage(BasePlayer player, string message, params object[] args) => string.Format(lang.GetMessage(message, this, player.UserIDString), args);
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string>() {
                {
                    "Chat.Prefix", "<color=red>[FurnaceUpgrades]</color>"
                }
                , {
                    "Error.NoPermission", "You don't have permission to update this oven"
                }
                , {
                    "Error.NoPermission.AutoFuel", "You don't have permission to toggle the auto fuel."
                }
                , {
                    "Error.NoPermission.AutoSplit", "You don't have permission to toggle the auto split."
                }
                , {
                    "Error.NotEnoughMoney", "You don't have enough money to upgrade this attribute"
                }
                , {
                    "Error.OwnerOnly", "Only the owner can update the oven attributes."
                }
                , {
                    "Error.OwnerOnly.CanRemove", "Only the owner of a upgraded furnace can remove it"
                }
                , {
                    "Error.OnlyTeamMates", "Only the furnace owner's teammates can upgrade this furnace."
                }
                , {
                    "Error.OnlyTeamMates.CanRemove", "Only the furnace owner's teammates can remove this furnace"
                }
                , {
                    "Notification.SmeltingSpeedUpgraded", "The smelting speed has been upgraded for <color=red>-${0}</color>"
                }
                , {
                    "Notification.FuelSpeedUpgraded", "The fuel speed has been upgraded for <color=red>-${0}</color>"
                }
                , {
                    "Notification.ResourceOutputUpgraded", "The resource output multiplier has been upgraded for <color=red>-${0}</color>"
                }
                , {
                    "Notification.CharcoalMultiplierUpgraded", "The charcoal multiplier has been upgraded for <color=red>-${0}</color>"
                }
                , {
                    "UI.UpgradeButton", "UPGRADE"
                }
                , {
                    "UI.StatusTitle", "<b>STATUS:</b>"
                }
                , {
                    "UI.SmeltingSpeedStatus", "Smelting speed: <color=orange>{0}x</color>"
                }
                , {
                    "UI.FuelSpeedStatus", "Fuel speed: <color=orange>{0}x</color>"
                }
                , {
                    "UI.ResourceOutputStatus", "Resource output: <color=orange>{0}x</color>"
                }
                , {
                    "UI.CharcoalMultiplierStatus", "Charcoal multiplier: <color=orange>{0}x</color>"
                }
                , {
                    "UI.OptionsLabel", "<b>OPTIONS:</b>"
                }
                , {
                    "UI.NoOptionAvailable", "No option available =/"
                }
                , {
                    "UI.AutoFuelOptionLabel", "Auto add fuel"
                }
                , {
                    "UI.AutoSplitOptionLabel", "Auto split added ores"
                }
                , {
                    "UI.StatusTemplate", "<b>{0}x » <color=orange>{1}x</color></b>"
                }
                , {
                    "UI.StatusMaxLevel", "<b>MAX: <color=orange>{0}x</color></b>"
                }
                , {
                    "UI.UpgradeTemplate", "UPGRADE FOR ${0}"
                }
                , {
                    "UI.MaxLevelUpgrade", "✔ MAX LEVEL REACHED"
                }
                , {
                    "UI.SmeltingSpeed.Title", "<b>SMELTING SPEED</b>"
                }
                , {
                    "UI.SmeltingSpeed.Description", "Increases the speed of the ore smelting process"
                }
                , {
                    "UI.FuelSpeed.Title", "<b>FUEL SPEED</b>"
                }
                , {
                    "UI.FuelSpeed.Description", "Increases the speed at which fuel is burned"
                }
                , {
                    "UI.ResourceOutput.Title", "<b>RESOURCE OUTPUT</b>"
                }
                , {
                    "UI.ResourceOutput.Description", "Increases the resource production by tick"
                }
                , {
                    "UI.CharcoalMultiplier.Title", "<b>CHARCOAL MULTIPLIER</b>"
                }
                , {
                    "UI.CharcoalMultiplier.Description", "Increases the charcoal production by tick"
                }
            }
            , this);
        }
#endregion
#region Initialization
        private void Init() {
            Unsubscribe(nameof(CanMoveItem));
            Unsubscribe(nameof(CanStackItem));
            Unsubscribe(nameof(CanCombineDroppedItem));
            Unsubscribe(nameof(OnEntityBuilt));
        }
        private void OnServerInitialized() {
            _instance = this;
            _controller = new OvenController();
            LoadData();
            CheckConflictPlugins();
            if (_config.Features.AutoFuel || _config.Features.AutoSplit) {
                Subscribe(nameof(CanMoveItem));
            }
            if (_config.General.KeepAttributes) {
                Subscribe(nameof(OnEntityBuilt));
                if (!StackModifier || !StackModifier.IsLoaded) {
                    Subscribe(nameof(CanStackItem));
                    Subscribe(nameof(CanCombineDroppedItem));
                }
                else {
                    PrintWarning("If the StackModifier plugin oven stack is greater than (1), upgrades will be lost, FurnaceUpgrades does not work correctly when changing the Furnace Stack using StackModifier!");
                }
            }
            permission.RegisterPermission(USE_PERMISSION, this);
            permission.RegisterPermission(AUTO_FUEL_PERMISSION, this);
            permission.RegisterPermission(AUTO_SPLIT_PERMISSION, this);
            if (ImageLibrary) {
                ImageLibrary.CallHook("ImportImageList", Title, _images, 0ul, true);
                var imageList = _ovensPrefab.Keys.Where((x) => x != "legacyfurnace").Select((x) => new KeyValuePair<string, ulong>(x, 0ul)).ToList();
                ImageLibrary.CallHook("LoadImageList", Title, imageList);
            }
            _setupOvensCoroutine = ServerMgr.Instance.StartCoroutine(_controller.SetupOvens());
        }
        private void OnNewSave(string FileName) {
            Puts("New save detected, resetting data...");
            _furnacesData.Clear();
            SaveData();
        }
#endregion
#region Plugin loads check
        private void OnPluginLoaded(Plugin plugin) {
            if (_conflictPlugins.Contains(plugin.Name)) CheckConflictPlugins();
        }
        private void OnPluginUnloaded(Plugin plugin) => OnPluginLoaded(plugin);
        private bool CheckConflictPlugins() {
            string? conflictPlugin = _conflictPlugins.FirstOrDefault(x => plugins.Exists(x));
            if (!string.IsNullOrEmpty(conflictPlugin)) {
                Unsubscribe(nameof(CanStackItem));
                Unsubscribe(nameof(CanCombineDroppedItem));
                PrintWarning($"The CanStackItem, CanCombineDroppedItem hook's was unsubscribed due to conflicts with the '{conflictPlugin}' plugin");
                return true;
            }
            else {
                if (_config.General.KeepAttributes) {
                    Subscribe(nameof(CanStackItem));
                    Subscribe(nameof(CanCombineDroppedItem));
                }
            }
            return false;
        }
#endregion
#region Hooks
        private void Unload() {
            if (!_setupOvensCoroutine.IsUnityNull()) {
                ServerMgr.Instance.StopCoroutine(_setupOvensCoroutine);
                _setupOvensCoroutine = null;
            }
            foreach (var player in BasePlayer.activePlayerList) DestroyUI(player);
            _controller.CleanupOvens();
            _furnacesData = null;
            _config = null;
            _instance = null;
        }
        private void OnEntitySpawned(BaseOven oven) {
            if (!oven.OwnerID.IsSteamId()) return;
            if (!_ovensPrefab.ContainsValue(oven.PrefabName)) return;
            _controller.InstallComponent(oven);
        }
        private object CanMoveItem(Item item, PlayerInventory playerLoot, ItemContainerId targetContainerId, int targetSlot, int amount) {
            if (item == null || !playerLoot) return null;
            if (!playerLoot.TryGetComponent<BasePlayer>(out var player)) return null;
            BaseOven oven = playerLoot.loot.entitySource as BaseOven;
            if (!oven) return null;
            ItemContainer targetContainer = playerLoot.FindContainer(targetContainerId);
            if (targetContainer != null && !(targetContainer?.entityOwner is BaseOven)) return null;
            ItemContainer container = oven.inventory;
            ItemContainer originalContainer = item.GetRootContainer();
            if (container == null || originalContainer == null || container == originalContainer || originalContainer?.entityOwner is BaseOven) return null;
            BaseOven.MinMax? allowedSlots = oven.GetAllowedSlots(item);
            if (allowedSlots is null) return null;
            for (int i = allowedSlots.Value.Min; i <= allowedSlots.Value.Max; i++) {
                Item slot = oven.inventory.GetSlot(i);
                if (slot != null && slot.info.shortname != item.info.shortname) return null;
            }
            if (!item.info.TryGetComponent<ItemModCookable>(out var cookable) || oven.IsOutputItem(item)) return null;
            if (cookable.lowTemp > oven.cookingTemperature || cookable.highTemp < oven.cookingTemperature) return null;
            if (!_furnacesData.TryGetValue(oven.net.ID.Value, out var furnaceData)) furnaceData = new FurnaceData();
            // Move the splitted items
            if (_config.Features.AutoSplit && furnaceData.useAutoSplit) MoveSplitItem(item, oven, amount);
            // Auto add fuel
            if (oven.allowByproductCreation && _config.Features.AutoFuel && furnaceData.useAutoFuel) NextTick(() => AutoAddFuel(playerLoot, oven));
            return (_config.Features.AutoSplit && furnaceData.useAutoSplit) ? true : null;
        }
#region Open/Close UI Hooks
        private void OnLootEntity(BasePlayer player, BaseOven oven) {
            if (player.IsInTutorial || !oven.OwnerID.IsSteamId()) return;
            if (_config.General.OwnerOnly && oven.OwnerID != player.userID) return;
            if (_config.General.OnlyTeamMates && oven.OwnerID != player.userID && !IsTeamMate(player, oven.OwnerID)) return;
            if (!_ovensPrefab.ContainsValue(oven.PrefabName)) return;
            if (!oven.HasComponent<OvenComponent>()) return;
            ShowUpgradeButton(player, oven);
            ShowOvenStatus(player, oven);
        }
        private void OnLootEntityEnd(BasePlayer player, BaseOven oven) {
            DestroyUI(player);
        }
#endregion
#region Oven Hooks
        private object OnOvenToggle(BaseOven oven, BasePlayer player) {
            if (!oven.TryGetComponent<OvenComponent>(out var component)) return null;
            if (oven.IsOn()) component.StopCooking();
            else {
                oven.StopCooking();
                component.StartCooking();
            }
            return false;
        }
        private object OnOvenStart(BaseOven oven) {
            if (!oven.TryGetComponent<OvenComponent>(out var component)) return null;
            component.StartCooking();
            return false;
        }
#endregion
#region Stack Fixes
        private object CanStackItem(Item source, Item target) {
            if (source == null || target == null) return null;
            if (_furnacesData.ContainsKey(source.uid.Value) || _furnacesData.ContainsKey(target.uid.Value)) return false;
            return null;
        }
        private object CanCombineDroppedItem(DroppedItem item, DroppedItem targetItem) => CanStackItem(item?.item, targetItem?.item);
#endregion
        private void OnEntityBuilt(Planner planner, GameObject gameObject) {
            BasePlayer player = planner.GetOwnerPlayer();
            if (!player) return;
            Item item = player.GetActiveItem();
            if (item == null || !_ovensPrefab.ContainsKey(item.info.shortname)) return;
            if (!gameObject.TryGetComponent<BaseOven>(out var oven)) return;
            if (!_furnacesData.TryGetValue(item.uid.Value, out var itemData)) return;
            _furnacesData.Remove(item.uid.Value);
            _furnacesData[oven.net.ID.Value] = itemData;
            itemData.type = FurnaceDataType.Furnace;
            SaveData();
            NextTick(() => {
                if (oven.TryGetComponent<OvenComponent>(out var component)) component.UpdateProperties();
                oven.inventory.Clear();
                oven.inventory.MarkDirty();
            }
            );
        }
        private bool? CanPickupEntity(BasePlayer player, BaseOven oven) {
            if (!oven.HasComponent<OvenComponent>()) return null;
            if (!IsVanillaFurnace(oven) && _config.General.KeepAttributes) {
                if (_config.General.OwnerOnly && oven.OwnerID != player.userID) {
                    SendMessage(player, "Error.OwnerOnly.CanRemove");
                    return false;
                }
                if (_config.General.OnlyTeamMates && oven.OwnerID != player.userID && !IsTeamMate(player, oven.OwnerID)) {
                    SendMessage(player, "Error.OnlyTeamMates.CanRemove");
                    return false;
                }
            }
            if (TryGiveOvenWithAttributes(player, oven)) {
                oven.Kill();
                return false;
            }
            return null;
        }
#region RemoverTool plugin
        private object canRemove(BasePlayer player, BaseOven oven) {
            if (!oven.HasComponent<OvenComponent>() || IsVanillaFurnace(oven)) return null;
            if (_config.General.KeepAttributes) {
                if (_config.General.OwnerOnly && oven.OwnerID != player.userID) return GetMessage(player, "Error.OwnerOnly.CanRemove");
                if (_config.General.OnlyTeamMates && oven.OwnerID != player.userID && !IsTeamMate(player, oven.OwnerID)) return GetMessage(player, "Error.OnlyTeamMates.CanRemove");
            }
            return null;
        }
        private object OnRemovableEntityInfo(BaseEntity entity, BasePlayer player) {
            if (!_config.General.KeepAttributes) return null;
            if (!(entity is BaseOven oven) || !oven.HasComponent<OvenComponent>()) return null;
            if (!_furnacesData.TryGetValue(oven.net.ID.Value, out var furnaceData)) return null;
            string itemName = _ovensPrefab.First((x) => x.Value == entity.PrefabName).Key;
            ItemDefinition itemDef = ItemManager.FindItemDefinition(itemName);
            if (!itemDef) return null;
            string displayName = $"{itemDef.displayName.english} - UPGRADED";
            return new Dictionary<string, object>() {
                {
                    "DisplayName", displayName
                }
                , {
                    "Refund", new Dictionary<string, object> {
                        {
                            "furnaceupgrades.furnace", new Dictionary<string, object> {
                                {
                                    "Amount", 1
                                }
                                , {
                                    "DisplayName", displayName
                                }
                            }
                        }
                    }
                }
            }
            ;
        }
        private object OnRemovableEntityGiveRefund(BaseEntity entity, BasePlayer player, string itemName) {
            if (!(entity is BaseOven oven) || !oven.HasComponent<OvenComponent>()) return null;
            if (itemName != "furnaceupgrades.furnace") return null;
            if (!TryGiveOvenWithAttributes(player, oven)) return false;
            return null;
        }
#endregion
#region BuildTools Plugin
        private object CanBuildToolsGiveRefund(BasePlayer player, BaseEntity entity) {
            if (!(entity is BaseOven oven) || !oven.HasComponent<OvenComponent>()) return null;
            if (TryGiveOvenWithAttributes(player, oven)) return false;
            return null;
        }
#endregion
#endregion
#region Functions
        private void MoveSplitItem(Item item, BaseOven oven, int splitAmount) {
            ItemContainer container = oven.inventory;
            int numOreSlots = oven.inputSlots;
            int totalMoved = 0;
            int itemAmount = item.amount > splitAmount ? splitAmount : item.amount;
            int totalAmount = Math.Min(itemAmount + container.itemList.Where(slotItem => slotItem.info == item.info).Take(numOreSlots).Sum(slotItem => slotItem.amount), Math.Abs(item.info.stackable * numOreSlots));
            if (numOreSlots <= 0) {
                return;
            }
            int totalStackSize = Math.Min(totalAmount / numOreSlots, item.info.stackable);
            int remaining = totalAmount - totalAmount / numOreSlots * numOreSlots;
            List<int> addedSlots = Pool.Get<List<int>>();
            List<OvenSlot> ovenSlots = Pool.Get<List<OvenSlot>>();
            for (int i = 0; i < numOreSlots; ++i) {
                Item existingItem;
                int slot = FindMatchingSlotIndex(oven, container, out existingItem, item.info, addedSlots);
                if (slot == -1) {
                    return;
                }
                addedSlots.Add(slot);
                OvenSlot ovenSlot = new OvenSlot {
                    Position = existingItem?.position, Index = slot, Item = existingItem
                }
                ;
                int currentAmount = existingItem?.amount ?? 0;
                int missingAmount = totalStackSize - currentAmount + (i < remaining ? 1 : 0);
                ovenSlot.DeltaAmount = missingAmount;
                if (currentAmount + missingAmount <= 0) continue;
                ovenSlots.Add(ovenSlot);
            }
            Pool.FreeUnmanaged(ref addedSlots);
            foreach (OvenSlot slot in ovenSlots) {
                if (slot.Item == null) {
                    Item newItem = ItemManager.Create(item.info, slot.DeltaAmount, item.skin);
                    slot.Item = newItem;
                    newItem.MoveToContainer(container, slot.Position ?? slot.Index);
                }
                else {
                    slot.Item.amount += slot.DeltaAmount;
                }
                totalMoved += slot.DeltaAmount;
            }
            container.MarkDirty();
            Pool.FreeUnmanaged(ref ovenSlots);
            if (totalMoved >= item.amount) {
                item.Remove();
                item.GetRootContainer()?.MarkDirty();
                return;
            }
            else {
                item.amount -= totalMoved;
                item.GetRootContainer()?.MarkDirty();
                return;
            }
        }
        private void AutoAddFuel(PlayerInventory playerInventory, BaseOven oven) {
            OvenInfo ovenInfo = GetOvenInfo(oven);
            int neededFuel = (int)Math.Ceiling(ovenInfo.FuelNeeded) - oven.inventory.GetAmount(oven.fuelType.itemid, false);
            var playerFuel = playerInventory.FindItemsByItemID(oven.fuelType.itemid);
            if (neededFuel <= 0 || playerFuel.Count <= 0) return;
            int fuelSlotIndex = 0;
            foreach (var item in playerFuel) {
                Item existingFuel = oven.inventory.GetSlot(fuelSlotIndex);
                if (existingFuel != null && existingFuel.amount >= existingFuel.info.stackable) {
                    if (fuelSlotIndex < oven.fuelSlots) fuelSlotIndex++;
                    else break;
                }
                Item largestFuelStack = oven.inventory.itemList.Where(x => x.info == oven.fuelType).OrderByDescending(x => item.amount).FirstOrDefault();
                int toTake = Math.Min(neededFuel, (oven.fuelType.stackable * oven.fuelSlots) - (largestFuelStack?.amount ?? 0));
                if (toTake <= 0) break;
                if (toTake > item.amount) toTake = item.amount;
                neededFuel -= toTake;
                int currentFuelAmount = oven.inventory.GetAmount(oven.fuelType.itemid, false);
                if (currentFuelAmount >= oven.fuelType.stackable * oven.fuelSlots) break;
                if (toTake >= item.amount) {
                    item.MoveToContainer(oven.inventory, fuelSlotIndex);
                }
                else {
                    Item splitItem = item.SplitItem(toTake);
                    if (!splitItem.MoveToContainer(oven.inventory, fuelSlotIndex)) break;
                }
                if (neededFuel <= 0) break;
            }
        }
        private UpgradeResult TryUpgradeAttribute(BasePlayer player, BaseOven oven, FeatureType type) {
            UpgradeSettings.Upgrade nextUpgrade = GetNextUpgrade(oven, type);
            if (nextUpgrade == null) return new UpgradeResult(UpgradeResult.UpgradeResultType.MaxLevel, 0);
            if (!TryTakeMoney(player, nextUpgrade.Cost)) return new UpgradeResult(UpgradeResult.UpgradeResultType.NotEnoughMoney, nextUpgrade.Cost);
            if (!_furnacesData.TryGetValue(oven.net.ID.Value, out var furnaceData)) furnaceData = new FurnaceData();
            switch (type) {
                case FeatureType.SmeltingSpeed : furnaceData.levels.smeltingSpeed++;
                break;
                case FeatureType.FuelSpeed : furnaceData.levels.fuelSpeed++;
                break;
                case FeatureType.ResourceOutput : furnaceData.levels.resourceOutput++;
                break;
                case FeatureType.CharcoalMultiplier : furnaceData.levels.charcoalMultiplier++;
                break;
            }
            _furnacesData[oven.net.ID.Value] = furnaceData;
            SaveData();
            return new UpgradeResult(UpgradeResult.UpgradeResultType.Success, nextUpgrade.Cost);
        }
        private bool TryGiveOvenWithAttributes(BasePlayer player, BaseOven oven) {
            string ovenName = _ovensPrefab.FirstOrDefault((x) => x.Value == oven.PrefabName).Key;
            if (string.IsNullOrEmpty(ovenName)) return false;
            if (!_furnacesData.TryGetValue(oven.net.ID.Value, out var furnaceData)) return false;
            if (!_config.General.KeepAttributes) {
                _furnacesData.Remove(oven.net.ID.Value);
                SaveData();
                return false;
            }
            Item item = ItemManager.CreateByName(ovenName, 1, oven.skinID);
            if (item == null) return false;
            item.name = $"{item.info.displayName.english} - UPGRADED";
            _furnacesData.Remove(oven.net.ID.Value);
            _furnacesData[item.uid.Value] = furnaceData;
            furnaceData.type = FurnaceDataType.Item;
            SaveData();
            if (!item.MoveToContainer(player.inventory.containerBelt, -1, false) && !item.MoveToContainer(player.inventory.containerMain, -1, false)) item.Drop(player.inventory.containerMain.dropPosition, player.inventory.containerMain.dropVelocity);
            return true;
        }
#endregion
#region Helpers
        private BaseOven GetOvenById(NetworkableId ovenId) {
            return BaseNetworkable.serverEntities.Find(ovenId) as BaseOven;
        }
        private bool TryTakeMoney(BasePlayer player, int amount) {
            switch (_config.Currency.Type) {
                case CurrencyType.Economics : return Economics.Call<bool>("Withdraw", player.UserIDString, (double)amount);
                case CurrencyType.ServerRewards : {
                    int balance = ServerRewards.Call<int>("CheckPoints", player.userID);
                    if (balance < amount) return false;
                    object result = ServerRewards.CallHook("TakePoints", player.userID, amount);
                    return result is bool ? (bool)result : false;
                }
                default : {
                    int acc = 0;
                    List<Item> toTake = Pool.Get<List<Item>>();
                    foreach (var item in player.inventory.containerMain.itemList) {
                        if (item.info.shortname == _config.Currency.Item.ShortName && item.skin == _config.Currency.Item.SkinID) {
                            acc += item.amount;
                            toTake.Add(item);
                            if (acc >= amount) break;
                        }
                    }
                    // Process containerMain if still required
                    if (acc < amount) {
                        foreach (var item in player.inventory.containerBelt.itemList) {
                            if (item.info.shortname == _config.Currency.Item.ShortName && item.skin == _config.Currency.Item.SkinID) {
                                acc += item.amount;
                                toTake.Add(item);
                                if (acc >= amount) break;
                            }
                        }
                    }
                    if (acc < amount) {
                        Pool.FreeUnmanaged(ref toTake);
                        return false;
                    }
                    int remaining = amount;
                    foreach (var item in toTake) {
                        if (item.amount > remaining) {
                            item.UseItem(remaining);
                            remaining = 0;
                        }
                        else {
                            remaining -= item.amount;
                            item.Remove();
                        }
                        item.MarkDirty();
                        if (remaining < 1) break;
                    }
                    Pool.FreeUnmanaged(ref toTake);
                    return true;
                }
            }
        }
        private OvenStatus GetOvenStatus(BaseOven oven) {
            return new OvenStatus() {
                SmeltingSpeed = GetCurrentUpgrade(oven, FeatureType.SmeltingSpeed)?.Multiplier ?? _config.Defaults.SmeltingSpeed, FuelSpeed = GetCurrentUpgrade(oven, FeatureType.FuelSpeed)?.Multiplier ?? _config.Defaults.FuelSpeed, ResourceOutput = GetCurrentUpgrade(oven, FeatureType.ResourceOutput)?.Multiplier ?? _config.Defaults.ResourceOutput, CharcoalMultiplier = GetCurrentUpgrade(oven, FeatureType.CharcoalMultiplier)?.Multiplier ?? _config.Defaults.CharcoalMultiplier
            }
            ;
        }
        private UpgradeSettings.Upgrade GetCurrentUpgrade(BaseOven oven, FeatureType type) {
            string ovenName = _ovensPrefab.FirstOrDefault((x) => x.Value == oven.PrefabName).Key;
            _furnacesData.TryGetValue(oven.net.ID.Value, out var furnaceData);
            int currentLevel = type switch {
                FeatureType.SmeltingSpeed => furnaceData?.levels.smeltingSpeed ?? 0, FeatureType.FuelSpeed => furnaceData?.levels.fuelSpeed ?? 0, FeatureType.ResourceOutput => furnaceData?.levels.resourceOutput ?? 0, _ => furnaceData?.levels.charcoalMultiplier ?? 0,
            }
            ;
            UpgradeSettings settings = _config.Upgrades[ovenName];
            UpgradeSettings.Upgrade[] upgrades = type switch {
                FeatureType.SmeltingSpeed => settings.SmeltingSp
// ... [Code preview truncated due to length. Full source in attached file] ...

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