OnOvenCooked
OnOvenCooked is called by BaseOven.Cook each time the oven finishes processing one cooking slot, after the fuel and input are consumed and the result item is produced.
void OnOvenCooked(BaseOven oven, Item item, BaseEntity slot)Parameters
| Parameter | Type | Description |
|---|---|---|
oven | BaseOven | The BaseOven that just finished cooking a slot. Use it for its position, owner (OwnerID), building privilege and inventory. |
item | Item | The Item that was cooked this tick. Its skin, amount and info.shortname tell you exactly what came out of the slot. |
slot | BaseEntity | The BaseEntity occupying that cooking slot (the item entity rendered inside the oven), or null when the slot has no attached entity. |
Return value
The return value is ignored. The injection uses a plain continue behavior and BaseOven.Cook returns void, so returning null or any value has no effect on the cooking logic.
How it works
The hook fires inside BaseOven.Cook, immediately after the oven's own OnCooked() call and after any burnable fuel item in that slot has been consumed. It runs once per cooking slot that advanced, not once per oven tick, so a large furnace with several full slots calls it repeatedly in a single processing pass. oven is the appliance (BaseOven, which also covers furnaces, campfires, BBQs and similar cookers), item is the item that was just produced or processed in that slot, and slot is the entity in the slot, which can be null.
Declaring the first parameter as BaseOven is already the narrowest useful type for cooking; there is no more specific oven class to filter on. You can still filter by item.info.shortname or by the oven's prefab. The surrounding code calls the hook with the return value ignored, so it is a pure notification: you cannot cancel, alter or substitute the cooking result from here. Use it for tracking output, awarding bonuses, or reacting to specific recipes.
Example plugin: Award bonus charcoal for wood burned in furnaces
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Furnace Charcoal Bonus", "RustPluginGenerator", "1.0.0")]
[Description("Grants extra charcoal to the owner when a furnace produces charcoal.")]
public class FurnaceCharcoalBonus : RustPlugin
{
private const string PermUse = "furnacecharcoalbonus.use";
private const string CookedShortname = "charcoal";
private PluginConfig config;
private readonly Dictionary<ulong, float> cooldowns = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Bonus charcoal per cook")]
public int BonusAmount = 2;
[JsonProperty("Cooldown per oven in seconds")]
public float CooldownSeconds = 60f;
[JsonProperty("Only for permission holders")]
public bool PermissionOnly = false;
}
protected override void LoadDefaultConfig() => config = new PluginConfig();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<PluginConfig>();
if (config == null) throw new Exception();
}
catch
{
PrintWarning("Configuration file is invalid, using defaults");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["BonusGiven"] = "Your furnace produced {0} bonus charcoal.",
["BonusDropped"] = "Your inventory was full, {0} bonus charcoal dropped at your feet."
}, this);
}
private string Msg(string key, string userId = null, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
private void Init()
{
permission.RegisterPermission(PermUse, this);
}
private void OnOvenCooked(BaseOven oven, Item item, BaseEntity slot)
{
if (oven == null || item == null || item.info == null) return;
if (item.info.shortname != CookedShortname) return;
ulong ownerId = oven.OwnerID;
if (ownerId == 0) return;
if (config.PermissionOnly && !permission.UserHasPermission(ownerId.ToString(), PermUse)) return;
ulong ovenId = oven.net != null ? oven.net.ID.Value : 0;
float now = UnityEngine.Time.realtimeSinceStartup;
float last;
if (ovenId != 0 && cooldowns.TryGetValue(ovenId, out last) && now - last < config.CooldownSeconds) return;
if (ovenId != 0) cooldowns[ovenId] = now;
BasePlayer owner = BasePlayer.FindByID(ownerId);
if (owner == null || !owner.IsConnected) return;
Item bonus = ItemManager.CreateByName(CookedShortname, config.BonusAmount);
if (bonus == null) return;
if (!owner.inventory.GiveItem(bonus))
{
bonus.Drop(owner.transform.position + Vector3.up, Vector3.zero);
owner.ChatMessage(Msg("BonusDropped", owner.UserIDString, config.BonusAmount));
}
else
{
owner.ChatMessage(Msg("BonusGiven", owner.UserIDString, config.BonusAmount));
}
}
private void Unload()
{
cooldowns.Clear();
}
}
}The plugin listens on OnOvenCooked and checks whether the produced item is charcoal, which is what a furnace yields when it burns wood. When it matches, it gives the oven's owner a configurable number of extra charcoal, respecting a per-oven cooldown stored in a dictionary keyed by the oven's network ID so a single furnace cannot be farmed every tick. Owners are resolved from oven.OwnerID and must be connected; the extra items are created with ItemManager.CreateByName and moved into the owner's main inventory, or dropped at the owner's feet if the inventory is full. Cooldowns are cleaned up in Unload.
Common use cases
Bonus output for specific recipes
Detect when a particular item shortname is cooked and grant extra resources to the owner, with a cooldown so it stays balanced.
Track furnace activity per base
Store the network ID, position and owner of each oven that cooks, then use that data for raid/decay checks or admin reports.
Fire effects or sounds on cooking
Run a small prefab effect or sound at the oven position when a slot finishes, for example to make active furnaces more visible.
Pitfalls
It fires per slot, not per cycle
A furnace with several filled slots calls the hook multiple times in one processing pass. Add your own cooldown or aggregate before granting anything per-oven.
The result cannot be changed
The hook runs after the item has been produced and the return value is ignored, so you cannot cancel or replace the cooked item from here.
slot may be null
The third parameter can be null when no entity is attached to the slot. Never dereference it without a null check.
Build a plugin with OnOvenCooked
Describe what should happen and get a compiled plugin that uses this hook.
Edit the prompt on the next screen. 2 free plugins a month, no card.
Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.
Build a plugin with OnOvenCooked
Generate