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.5")]
[Description("Upgrade your furnaces and improve smelting!")]
internal class FurnaceUpgrades : RustPlugin {
/*------------------------------------
*
* FurnaceUpgrades by Ifte
* Support: https://discord.gg/cCWadjcapr
* Fiverr: https://www.fiverr.com/s/e2pkYY
* Eror404 not found
*
-------------------------------------*/
/* Version: 2.5.5
* - Added new config values, "Requires upgrade button permission" and "Requires show status permission" false by default
* - Added support for Loottable plugin
* - Fixed null reference error on mixing table
*/
/* Version: 2.5.4
* - Added new feature for mixing table
* - Added new configuration for mixing table in the config
* - Only Allow Oven Toggling by Owner & Team": false (config)
*/
/* 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
//{ "mixingtable.deployed", "assets/prefabs/deployable/mixingtable/mixingtable.deployed.prefab" }
[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 const string UPGRADE_Button_PERMISSION = "FurnaceUpgrades.showupgrade";
private const string STATUS_UI_PERMISSION = "FurnaceUpgrades.showstatus";
private readonly bool doDebug = false;
private readonly string[] _conflictPlugins = new string[] {
"StacksExtended", "StackModifier", "StackSizeController", "Loottable"
}
;
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"
}
, {
"mixingtable.deployed", "https://i.postimg.cc/V6J6h040/mixingtable.png"
}
}
;
private readonly Hash<ulong, BaseOven> _openModals = new Hash<ulong, BaseOven>();
private readonly Hash<ulong, MixingTable> _openModalsMixingTable = new Hash<ulong, MixingTable>();
//mixing table
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 MixingUpgradeType {
Speed, Output
}
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}/FurnaceData");
}
catch {
_furnacesData = new Dictionary<ulong, FurnaceData>();
}
if (_furnacesData == null) _furnacesData = new Dictionary<ulong, FurnaceData>();
}
private void SaveData() {
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/FurnaceData", _furnacesData);
}
private class MixingData ///mixing data
{
public FurnaceDataType type;
public Levels levels = new Levels();
public class Levels {
public int speedpercentage;
//public int resourceOutput;
}
}
private static Dictionary<ulong, MixingData> _MixingData;
private void LoadDataMixing() {
try {
_MixingData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, MixingData>>($"{Name}/MixingData");
}
catch {
_MixingData = new Dictionary<ulong, MixingData>();
}
if (_MixingData == null) _MixingData = new Dictionary<ulong, MixingData>();
}
private void SaveDataMixing() {
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/MixingData", _MixingData);
}
#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 UpgradeMixingTableSettings {
[JsonProperty("Enable Mixing Table upgrade")]
public bool EnableMixingTableUpgrade {
get;
set;
}
[JsonProperty("Mixing Table speed upgrade")]
public bool MixingTableSpeedUpgrade {
get;
set;
}
[JsonProperty("Mixing Table Speed in %(Max 100)")]
public Upgrade[] MixingTableSpeed {
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("Upgrade button on mixing table")]
public BasicSettings UpgradeButtonMixingTable {
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("Only Allow Oven Toggling by Owner & Team")]
public bool OnlyTeamMatesToggle {
get;
set;
}
[JsonProperty("Keep attributes when removing")]
public bool KeepAttributes {
get;
set;
}
[JsonProperty("Requires upgrade button permission")]
public bool ReqUpgradePerm {
get;
set;
}
[JsonProperty("Requires show status permission")]
public bool ReqStatusPerm {
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("Mixing Table Upgrade Settings", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public UpgradeMixingTableSettings MixingTableUpgrades {
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, OnlyTeamMatesToggle = false, KeepAttributes = true, ReqUpgradePerm = false, ReqStatusPerm = false,
}
, 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
}
, UpgradeButtonMixingTable = new UISettings.BasicSettings() {
Anchor = "0.5 0 0.5 0", Offset = "337 110.5 417 142.5", //400 109.5 480 141.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
}
, MixingTableUpgrades = new UpgradeMixingTableSettings() {
EnableMixingTableUpgrade = true, MixingTableSpeedUpgrade = true, MixingTableSpeed = new UpgradeMixingTableSettings.Upgrade[] {
new UpgradeMixingTableSettings.Upgrade(100, 10f), new UpgradeMixingTableSettings.Upgrade(300, 30f), new UpgradeMixingTableSettings.Upgrade(500, 50f),
}
,
}
, 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;
}
if (_config.Version < new VersionNumber(2, 5, 4)) {
Configuration baseconfig = GetBaseConfig();
_config.General.OnlyTeamMatesToggle = baseconfig.General.OnlyTeamMatesToggle;
_config.UI.UpgradeButtonMixingTable = baseconfig.UI.UpgradeButtonMixingTable;
_config.MixingTableUpgrades = baseconfig.MixingTableUpgrades;
}
if (_config.Version < new VersionNumber(2, 5, 5)) {
Configuration baseconfig = GetBaseConfig();
_config.General.ReqUpgradePerm = baseconfig.General.ReqUpgradePerm;
_config.General.ReqStatusPerm = baseconfig.General.ReqStatusPerm;
}
_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.MixingSpeedStatus", "Mixing speed: <color=orange>{0}%</color>"
}
, {
"UI.MixingOutputStatus", "Mixing output multiplier: <color=orange>{0}x</color>"
}
, {
"UI.MixingSpeed.Title", "<b>MIXING SPEED</b>"
}
, {
"UI.MixingSpeed.Description", "Increases the speed of mixing table"
}
, {
"UI.MixingOutput.Title", "<b>RESOURCE OUTPUT</b>"
}
, {
"UI.MixingOutput.Description", "Increases the resource production"
}
, {
"Notification.MixingSpeedUpgrade", "The mixing speed has been upgraded for <color=red>-${0}</color>"
}
, {
"Notification.MixingOutputUpgrade", "The mixing resource output has been upgraded for <color=red>-${0}</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 Commands
[ConsoleCommand("furnaceupgrades.ui")]
private void ConsoleCommandUI(ConsoleSystem.Arg arg) {
BasePlayer player = arg?.Player();
if (!player || !arg.HasArgs()) return;
switch (arg.Args[0].ToLower()) {
case "show" : {
if (!arg.HasArgs(2) || !ulong.TryParse(arg.Args[1], out ulong ovenId)) return;
BaseOven oven = GetOvenById(new NetworkableId(ovenId));
if (!oven || !oven.HasComponent<OvenComponent>()) return;
_openModals[player.userID] = oven;
ShowModal(player, oven);
return;
}
case "showmixing" : {
if (!arg.HasArgs(2) || !ulong.TryParse(arg.Args[1], out ulong mixingTableId)) return;
MixingTable mixingTable = GetMixingTableById(new NetworkableId(mixingTableId));
if (!mixingTable) return;
if (!_MixingData.ContainsKey(mixingTable.net.ID.Value)) {
_MixingData.Add(mixingTable.net.ID.Value, new MixingData());
SaveDataMixing();
}
_openModalsMixingTable[player.userID] = mixingTable;
ShowModalMixingTable(player, mixingTable);
return;
}
case "close" : {
CloseModal(player);
return;
}
case "toggle_option" : {
if (!_openModals.ContainsKey(player.userID)) return;
if (!arg.HasArgs(2) || !int.TryParse(arg.Args[1], out int type)) return;
if (!HasPermission(player, USE_PERMISSION)) {
SendMessage(player, "Error.NoPermission");
return;
}
if (type == 0 && !HasPermission(player, AUTO_FUEL_PERMISSION)) {
SendMessage(player, "Error.NoPermission.AutoFuel");
return;
}
else if (type == 1 && !HasPermission(player, AUTO_SPLIT_PERMISSION)) {
SendMessage(player, "Error.NoPermission.AutoSplit");
return;
}
BaseOven oven = _openModals[player.userID];
if (_config.General.OwnerOnly && oven.OwnerID != player.userID) {
SendMessage(player, "Error.OwnerOnly");
return;
}
if (_config.General.OnlyTeamMates && player.userID != oven.OwnerID && !IsTeamMate(player, oven.OwnerID)) {
SendMessage(player, "Error.OnlyTeamMates");
return;
}
if (!_furnacesData.TryGetValue(oven.net.ID.Value, out var furnaceData)) furnaceData = new FurnaceData();
if (type == 0) furnaceData.useAutoFuel = !furnaceData.useAutoFuel;
else if (type == 1) furnaceData.useAutoSplit = !furnaceData.useAutoSplit;
else return;
_furnacesData[oven.net.ID.Value] = furnaceData;
SaveData();
ShowModal(player, oven);
return;
}
case "upgrade" : {
if (!_openModals.ContainsKey(player.userID)) return;
if (!arg.HasArgs(2) || !Enum.TryParse<FeatureType>(arg.Args[1], out var upgradeType)) return;
if (!HasPermission(player, USE_PERMISSION)) {
SendMessage(player, "Error.NoPermission");
return;
}
BaseOven oven = _openModals[player.userID];
if (_config.General.OwnerOnly && oven.OwnerID != player.userID) {
SendMessage(player, "Error.OwnerOnly");
return;
}
if (_config.General.OnlyTeamMates && oven.OwnerID != player.userID && !IsTeamMate(player, oven.OwnerID)) {
SendMessage(player, "Error.OnlyTeamMates");
return;
}
string ovenName = _ovensPrefab.FirstOrDefault((x) => x.Value == oven.PrefabName).Key;
if (!_config.Upgrades.ContainsKey(ovenName) || !oven.TryGetComponent<OvenComponent>(out var component)) return;
UpgradeResult result = TryUpgradeAttribute(player, oven, upgradeType);
if (result.Type == UpgradeResult.UpgradeResultType.MaxLevel) return;
if (result.Type == UpgradeResult.UpgradeResultType.NotEnoughMoney) {
SendMessage(player, "Error.NotEnoughMoney");
return;
}
if (!string.IsNullOrEmpty(_config.Visual.UpgradeEffect)) Effect.server.Run(_config.Visual.UpgradeEffect, oven.transform.position, Vector3.zero, null, true );
component.UpdateProperties();
if (oven.IsOn()) component.StartCooking();
string messageKey = upgradeType switch {
FeatureType.SmeltingSpeed => "Notification.SmeltingSpeedUpgraded", FeatureType.FuelSpeed => "Notification.FuelSpeedUpgraded", FeatureType.ResourceOutput => "Notification.ResourceOutputUpgraded", _ => "Notification.CharcoalMultiplierUpgraded"
}
;
SendMessage(player, messageKey, result.Cost);
ShowOvenStatus(player, oven);
ShowModal(player, oven);
return;
}
case "upgrademixing" : {
if (!_openModalsMixingTable.ContainsKey(player.userID)) return;
if (!arg.HasArgs(2) || !Enum.TryParse<MixingUpgradeType>(arg.Args[1], out var upgradeType)) return;
if (!HasPermission(player, USE_PERMISSION)) {
SendMessage(player, "Error.NoPermission");
return;
}
MixingTable mixingTable = _openModalsMixingTable[player.userID];
if (_config.General.OwnerOnly && mixingTable.OwnerID != player.userID) {
SendMessage(player, "Error.OwnerOnly");
return;
}
if (_config.General.OnlyTeamMates && mixingTable.OwnerID != player.userID && !IsTeamMate(player, mixingTable.OwnerID)) {
SendMessage(player, "Error.OnlyTeamMates");
return;
}
UpgradeResult result = TryUpgradeAttribute(player, mixingTable, upgradeType);
if (result.Type == UpgradeResult.UpgradeResultType.MaxLevel) return;
if (result.Type == UpgradeResult.UpgradeResultType.NotEnoughMoney) {
SendMessage(player, "Error.NotEnoughMoney");
return;
}
if (!string.IsNullOrEmpty(_config.Visual.UpgradeEffect)) Effect.server.Run(_config.Visual.UpgradeEffect, mixingTable.transform.position, Vector3.zero, null, true );
string messageKey = upgradeType switch {
MixingUpgradeType.Speed => "Notification.MixingSpeedUpgrade", MixingUpgradeType.Output => "Notification.MixingOutputUpgrade",
}
;
SendMessage(player, messageKey, result.Cost);
ShowMixingStatus(player, mixingTable);
ShowModalMixingTable(player, mixingTable);
return;
}
}
}
#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();
LoadDataMixing();
//mixing data
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);
permission.RegisterPermission(UPGRADE_Button_PERMISSION, this);
permission.RegisterPermission(STATUS_UI_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) {
_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;
try {
ShowUpgradeButton(player, oven);
ShowOvenStatus(player, oven);
}
catch {
}
}
private void OnLootEntity(BasePlayer player, MixingTable mixingTable) ///mixing table
{
if (player.IsInTutorial || !mixingTable.OwnerID.IsSteamId()) return;
if (_config.General.OwnerOnly && mixingTable.OwnerID != player.userID) return;
if (_config.General.OnlyTeamMates && mixingTable.OwnerID != player.userID && !IsTeamMate(player, mixingTable.OwnerID)) return;
if (!_MixingData.TryGetValue(mixingTable.net.ID.Value, out var mixingData)) {
mixingData = new MixingData();
mixingData.type = FurnaceDataType.Furnace;
_MixingData[mixingTable.net.ID.Value] = mixingData;
SaveDataMixing();
}
try {
ShowUpgradeButtonMixingTable(player, mixingTable);
ShowMixingStatus(player, mixingTable);
}
catch {
}
}
private void OnLootEntityEnd(BasePlayer player, BaseOven oven) {
DestroyUI(player);
}
private void OnLootEntityEnd(BasePlayer player, MixingTable 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.OwnerID != player.userID && !IsTeamMate(player, oven.OwnerID) && _config.General.OnlyTeamMatesToggle) return true;
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)
// ... [Code preview truncated due to length. Full source in attached file] ...