Anyone know how to add the new industrial electric furnace to work with QuickSmelt Plugin?
I've tried adding both of these to the config and neither will work. Anyone have any idea?
``` "industrial.electric.furnace.deployed": 100.0,```
```"industrial.electric.furnace": 100.0,```
Does not work with the new Industrial Electric Furnace anyone have a fix?
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("Quick Smelt", "misticos", "5.1.5")]
[Description("Increases the speed of the furnace smelting, including Industrial Electric Furnaces.")]
class QuickSmelt : RustPlugin
{
#region Variables
private static QuickSmelt _instance;
private const string PermissionUse = "quicksmelt.use";
#endregion
#region Configuration
private static Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Use Permission")]
public bool UsePermission = true;
[JsonProperty(PropertyName = "Speed Multipliers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> SpeedMultipliers = new Dictionary<string, float>
{
{ "global", 1.0f },
{ "furnace.large", 2.0f },
{ "furnace", 1.5f },
// Ondersteuning voor Industriële Elektrische Oven
{ "industrial.electric.furnace.deployed", 5.0f }
};
[JsonProperty(PropertyName = "Fuel Usage Speed Multipliers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> FuelSpeedMultipliers = new Dictionary<string, float>
{
{ "global", 1.0f },
{ "furnace.large", 1.0f },
{ "furnace", 1.0f },
{ "industrial.electric.furnace.deployed", 1.0f }
};
[JsonProperty(PropertyName = "Fuel Usage Multipliers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> FuelUsageMultipliers = new Dictionary<string, int>
{
{ "global", 1 },
{ "furnace.large", 1 },
{ "furnace", 1 },
{ "industrial.electric.furnace.deployed", 1 }
};
[JsonProperty(PropertyName = "Output Multipliers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, Dictionary<string, float>> OutputMultipliers = new Dictionary<string, Dictionary<string, float>>
{
{
"global", new Dictionary<string, float>
{
{ "global", 1.0f }
}
},
{
"furnace.large", new Dictionary<string, float>
{
{ "metal.refined", 1.1f }
}
},
{
"industrial.electric.furnace.deployed", new Dictionary<string, float>
{
{ "global", 1.0f }
}
}
};
[JsonProperty(PropertyName = "Whitelist", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, List<string>> Whitelist = new Dictionary<string, List<string>>
{
{ "global", new List<string>() },
{ "industrial.electric.furnace.deployed", new List<string>() }
};
[JsonProperty(PropertyName = "Blacklist", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, List<string>> Blacklist = new Dictionary<string, List<string>>
{
{ "global", new List<string>() },
{ "industrial.electric.furnace.deployed", new List<string>() }
};
[JsonProperty(PropertyName = "Smelting Frequencies (Smelt items every N smelting ticks)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> SmeltingFrequencies = new Dictionary<string, int>
{
{ "global", 1 },
{ "industrial.electric.furnace.deployed", 1 }
};
[JsonProperty(PropertyName = "Debug")]
public bool Debug = false;
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
}
catch
{
PrintError("Your configuration file contains an error. Using default configuration values.");
LoadDefaultConfig();
}
}
protected override void LoadDefaultConfig() => _config = new Configuration();
protected override void SaveConfig() => Config.WriteObject(_config);
#endregion
#region Hooks
private void Unload()
{
var ovens = UnityEngine.Object.FindObjectsOfType<BaseOven>();
PrintDebug($"Processing BaseOven(s).. Amount: {ovens.Length}.");
for (var i = 0; i < ovens.Length; i++)
{
var oven = ovens[i];
var component = oven.GetComponent<FurnaceController>();
if (component != null)
{
if (oven.IsOn())
{
PrintDebug("Oven is on. Restarted cooking");
component.StopCooking();
oven.StartCooking();
}
UnityEngine.Object.Destroy(component);
}
}
PrintDebug("Done.");
}
private void OnServerInitialized()
{
_instance = this;
permission.RegisterPermission(PermissionUse, this);
var ovens = UnityEngine.Object.FindObjectsOfType<BaseOven>();
PrintDebug($"Processing BaseOven(s).. Amount: {ovens.Length}.");
for (var i = 0; i < ovens.Length; i++)
{
var oven = ovens[i];
OnEntitySpawned(oven);
}
timer.Once(1f, () =>
{
for (var i = 0; i < ovens.Length; i++)
{
var oven = ovens[i];
if (oven == null) continue;
var component = oven.gameObject.GetComponent<FurnaceController>();
if (oven.IsDestroyed || !oven.IsOn() || !CanUse(oven.OwnerID))
continue;
component?.StartCooking();
}
});
}
private void OnEntitySpawned(BaseNetworkable entity)
{
var oven = entity as BaseOven;
if (oven == null) return;
// Voeg de controller toe als deze nog niet bestaat
if (oven.gameObject.GetComponent<FurnaceController>() == null)
{
oven.gameObject.AddComponent<FurnaceController>();
}
}
private object OnOvenToggle(StorageContainer oven, BasePlayer player)
{
// Check if it's actually an oven
if (!(oven is BaseOven baseOven)) return null;
if (baseOven is BaseFuelLightSource || (baseOven.needsBuildingPrivilegeToUse && !player.CanBuild()))
return null;
PrintDebug("OnOvenToggle called");
var component = baseOven.gameObject.GetComponent<FurnaceController>();
// Als er geen component is (bijv. door een andere plugin verwijderd), doe niets
if (component == null) return null;
var canUse = CanUse(baseOven.OwnerID) || CanUse(player.userID);
if (baseOven.IsOn())
{
component.StopCooking();
}
else
{
if (canUse)
component.StartCooking();
else
{
PrintDebug($"No permission ({player.userID})");
return null;
}
}
return false; // Prevent default behavior if we handled it, or return null to let game handle it.
// Returning false here stops the vanilla toggle logic, which is what we want since StartCooking handles it.
}
#endregion
#region Helpers
private bool CanUse(ulong id) =>
!_config.UsePermission || permission.UserHasPermission(id.ToString(), PermissionUse);
private static void PrintDebug(string message)
{
if (_config.Debug)
Debug.Log($"DEBUG ({_instance.Name}) > " + message);
}
#endregion
#region Controller
public class FurnaceController : FacepunchBehaviour
{
private int _ticks;
private BaseOven _oven;
private BaseOven Furnace
{
get
{
if (_oven == null)
_oven = GetComponent<BaseOven>();
return _oven;
}
}
private float _speedMultiplier;
private float _fuelSpeedMultiplier;
private int _fuelUsageMultiplier;
private int _smeltingFrequency;
private Dictionary<string, float> _outputModifiers;
private float OutputMultiplier(string shortname)
{
float modifier;
if (_outputModifiers != null && _outputModifiers.TryGetValue(shortname, out modifier))
return modifier;
if (_outputModifiers != null && _outputModifiers.TryGetValue("global", out modifier))
return modifier;
return 1.0f;
}
private List<string> _blacklist;
private List<string> _whitelist;
private bool? IsAllowed(string shortname)
{
if (_blacklist != null && _blacklist.Contains(shortname))
return false;
if (_whitelist != null && _whitelist.Contains(shortname))
return true;
return null;
}
private void Awake()
{
if (Furnace == null) return;
string prefabName = Furnace.ShortPrefabName;
float modifierF;
int modifierI;
// Speed Multiplier
if (!_config.SpeedMultipliers.TryGetValue(prefabName, out modifierF) &&
!_config.SpeedMultipliers.TryGetValue("global", out modifierF))
modifierF = 1.0f;
// Hoe hoger de multiplier, hoe sneller het gaat.
// De originele code deed 0.5f / modifier. Dit betekent dat een multiplier van 2.0 de tijd halveert (2x zo snel).
_speedMultiplier = 0.5f / modifierF;
// Fuel Speed Multiplier
if (!_config.FuelSpeedMultipliers.TryGetValue(prefabName, out modifierF) &&
!_config.FuelSpeedMultipliers.TryGetValue("global", out modifierF))
modifierF = 1.0f;
_fuelSpeedMultiplier = modifierF;
// Fuel Usage Multiplier
if (!_config.FuelUsageMultipliers.TryGetValue(prefabName, out modifierI) &&
!_config.FuelUsageMultipliers.TryGetValue("global", out modifierI))
modifierI = 1;
_fuelUsageMultiplier = modifierI;
// Smelting Frequency
if (!_config.SmeltingFrequencies.TryGetValue(prefabName, out modifierI) &&
!_config.SmeltingFrequencies.TryGetValue("global", out modifierI))
modifierI = 1;
_smeltingFrequency = modifierI;
// Output Modifiers
if (!_config.OutputMultipliers.TryGetValue(prefabName, out _outputModifiers) &&
!_config.OutputMultipliers.TryGetValue("global", out _outputModifiers))
{
_outputModifiers = null;
}
// Lists
List<string> blackListTemp = null;
List<string> whiteListTemp = null;
bool hasBlacklist = _config.Blacklist.TryGetValue(prefabName, out blackListTemp) || _config.Blacklist.TryGetValue("global", out blackListTemp);
bool hasWhitelist = _config.Whitelist.TryGetValue(prefabName, out whiteListTemp) || _config.Whitelist.TryGetValue("global", out whiteListTemp);
if (hasBlacklist) _blacklist = blackListTemp;
if (hasWhitelist) _whitelist = whiteListTemp;
}
private Item FindBurnable()
{
if (Furnace.inventory == null)
return null;
var burnable = Interface.Call<Item>("OnFindBurnable", _oven);
if (burnable != null)
{
return burnable;
}
foreach (var item in Furnace.inventory.itemList)
{
if (!_oven.IsBurnableItem(item))
continue;
return item;
}
return null;
}
public void Cook()
{
if (Furnace == null || Furnace.IsDestroyed)
{
StopCooking();
return;
}
var itemBurnable = FindBurnable();
if (Interface.CallHook("OnOvenCook", this, itemBurnable) != null)
{
return;
}
if (itemBurnable == null)
{
StopCooking();
return;
}
SmeltItems();
// Mark items as cooking
foreach (var itemCooking in Furnace.inventory.itemList)
{
// Check if item is in input slots. Note: Industrial furnaces might have different slot layouts.
// BaseOven usually handles this via _inputSlotIndex and inputSlots.
if (itemCooking.position >= Furnace._inputSlotIndex &&
itemCooking.position < Furnace._inputSlotIndex + Furnace.inputSlots &&
!itemCooking.HasFlag(global::Item.Flag.Cooking))
{
itemCooking.SetFlag(global::Item.Flag.Cooking, true);
itemCooking.MarkDirty();
}
}
// Handle Fire Slot visuals/logic if applicable
var slot = Furnace.GetSlot(BaseEntity.Slot.FireMod);
if (slot)
{
slot.SendMessage("Cook", 0.5f, SendMessageOptions.DontRequireReceiver);
}
var burnable = itemBurnable.info.GetComponent<ItemModBurnable>();
if (burnable != null)
{
// Consume fuel
itemBurnable.fuel -= 0.5f * (Furnace.cookingTemperature / 200f) * _fuelSpeedMultiplier;
if (!itemBurnable.HasFlag(global::Item.Flag.OnFire))
{
itemBurnable.SetFlag(global::Item.Flag.OnFire, true);
itemBurnable.MarkDirty();
}
if (itemBurnable.fuel <= 0f)
{
ConsumeFuel(itemBurnable, burnable);
}
}
_ticks++;
Interface.CallHook("OnOvenCooked", this, itemBurnable, slot);
}
private void ConsumeFuel(Item fuel, ItemModBurnable burnable)
{
if (Interface.CallHook("OnFuelConsume", _oven, fuel, burnable) != null)
{
return;
}
if (Furnace.allowByproductCreation && burnable.byproductItem != null &&
Random.Range(0f, 1f) > burnable.byproductChance)
{
var def = burnable.byproductItem;
var item = ItemManager.Create(def,
(int)(burnable.byproductAmount * OutputMultiplier(def.shortname)));
if (!item.MoveToContainer(Furnace.inventory))
{
StopCooking();
item.Drop(Furnace.inventory.dropPosition, Furnace.inventory.dropVelocity);
}
}
if (fuel.amount <= _fuelUsageMultiplier)
{
fuel.Remove();
return;
}
fuel.UseItem(_fuelUsageMultiplier);
fuel.fuel = burnable.fuelAmount;
fuel.MarkDirty();
Interface.CallHook("OnFuelConsumed", _oven, fuel, burnable);
}
private void SmeltItems()
{
if (_ticks % _smeltingFrequency != 0)
return;
// Iterate backwards to safely remove items if needed, though usually we modify amount.
// Using a standard loop is fine as long as we don't remove from the list directly without care.
// We iterate a copy of the list or be careful. The original code iterated itemList directly.
// Let's stick to the original logic but ensure validity checks.
var itemList = Furnace.inventory.itemList;
for (var i = 0; i < itemList.Count; i++)
{
var item = itemList[i];
if (item == null || !item.IsValid())
continue;
var cookable = item.info.GetComponent<ItemModCookable>();
if (cookable == null)
continue;
var isAllowed = IsAllowed(item.info.shortname);
if (isAllowed != null && !isAllowed.Value)
continue;
var temperature = item.temperature;
// Check if cookable at current temperature
if (!cookable.CanBeCookedByAtTemperature(temperature) && isAllowed == null)
{
if (!cookable.setCookingFlag || !item.HasFlag(global::Item.Flag.Cooking))
continue;
item.SetFlag(global::Item.Flag.Cooking, false);
item.MarkDirty();
continue;
}
// Check cook time logic
if (cookable.cookTime > 0 && _ticks * 1f / _smeltingFrequency % cookable.cookTime > 0)
continue;
if (cookable.setCookingFlag && !item.HasFlag(global::Item.Flag.Cooking))
{
item.SetFlag(global::Item.Flag.Cooking, true);
item.MarkDirty();
}
// Calculate consumption based on speed
var amountConsumed = (int)_oven.GetSmeltingSpeed();
// Ensure we don't consume more than we have
amountConsumed = Math.Min(amountConsumed, item.amount);
if (amountConsumed <= 0) amountConsumed = 1; // Safety fallback
if (item.amount > amountConsumed)
{
item.amount -= amountConsumed;
item.MarkDirty();
}
else
{
item.Remove();
}
if (cookable.becomeOnCooked == null)
continue;
var producedAmount = (int)(cookable.amountOfBecome * amountConsumed * OutputMultiplier(cookable.becomeOnCooked.shortname));
if (producedAmount <= 0) producedAmount = 1;
var itemProduced = ItemManager.Create(cookable.becomeOnCooked, producedAmount);
if (itemProduced == null) continue;
if (!itemProduced.MoveToContainer(item.parent))
{
itemProduced.Drop(item.parent.dropPosition, item.parent.dropVelocity);
}
}
}
public void StartCooking()
{
if (Furnace == null) return;
if (FindBurnable() == null)
{
PrintDebug("No burnable.");
return;
}
StopCooking();
PrintDebug("Starting cooking..");
Furnace.inventory.temperature = Furnace.cookingTemperature;
Furnace.UpdateAttachmentTemperature();
PrintDebug($"Speed Multiplier: {_speedMultiplier}");
// InvokeRepeating takes (methodName, initialDelay, repeatRate)
Furnace.InvokeRepeating(Cook, _speedMultiplier, _speedMultiplier);
Furnace.SetFlag(BaseEntity.Flags.On, true);
}
public void StopCooking()
{
if (Furnace == null) return;
PrintDebug("Stopping cooking..");
Furnace.CancelInvoke(Cook);
Furnace.StopCooking();
}
}
#endregion
}
}
JSON
"Speed Multipliers": {
"global": 1.0,
"furnace": 2.0,
"furnace.large": 3.0,
"industrial.electric.furnace.deployed": 10.0
},
JSON
"Speed Multipliers": {
"global": 1.0,
"furnace": 2.0,
"furnace.large": 3.0,
"industrial.electric.furnace.deployed": 10.0
},