Skip to content
RustPluginGenerator

OnItemRecycleAmount

OnItemRecycleAmount is called inside `Recycler.RecycleThink` for every stack the recycler processes, before the scrap payout is calculated, and lets you override how many items are consumed in that tick.

Signature
object OnItemRecycleAmount(Item slot, int amount, Recycler recycler)

Parameters

Hook parameters
ParameterTypeDescription
slotItemThe item stack currently being processed by the recycler. Its `info`, `amount`, `MaxStackable()` and `info.Blueprint.scrapFromRecycle` are the values the recycler uses to decide how much to consume and how much scrap to yield.
amountintThe number of items the recycler intends to consume from this stack in this tick, computed by the game as 1 (single item) or 10% of `MaxStackable()` capped by the stack amount. Return an int to replace it.
recyclerRecyclerThe `Recycler` entity running `RecycleThink`. Use it to check ownership, position or storage contents when making a decision.

Return value

Return an int and it replaces the computed consume amount for this stack. Return null (or any non-int value) and the game's original calculation is used unchanged. The hook cannot cancel recycling; use OnItemRecycle for that.

How it works

This hook fires from Recycler.RecycleThink once per item stack the recycler takes from its inventory. The game first computes the consume amount: 1 when the stack holds one item, otherwise Mathf.CeilToInt(Mathf.Min(slot.amount, slot.MaxStackable() * 0.1f)) — roughly a tenth of a full stack, rounded up and clamped to the current stack size. The hook is called with that value as the amount parameter, together with the Item (slot) and the Recycler entity. Immediately after the hook, the game reads slot.info.Blueprint.scrapFromRecycle to work out the scrap output.

Return an int to replace the consume amount; anything else leaves the game's value in place. Because slot is the live item, returning a larger number does not by itself remove items — the recycler still consumes what it consumes internally — so the safe use is scaling the tick down or clamping it (for example to slow recycling on a rate-limited server). Fires very frequently while a recycler runs, so keep the body cheap and never print from it. There is no way to tell which player opened the recycler from the parameters; inspect recycler.inventory or OwnerID if you need ownership.

Example plugin: Cap recycler consumption to one item per tick

RecyclerAmountLimit.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Recycler Amount Limit", "RustPluginGenerator", "1.0.0")]
    [Description("Clamps how many items a recycler consumes per stack per tick, with a bypass permission.")]
    public class RecyclerAmountLimit : RustPlugin
    {
        private const string PermBypass = "recycleramountlimit.bypass";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Max items consumed per tick")]
            public int MaxPerTick = 1;
        }

        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>
            {
                ["Reloaded"] = "Recycler amount limit reloaded: max {0} item(s) per tick."
            }, 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(PermBypass, this);
        }

        private object OnItemRecycleAmount(Item slot, int amount, Recycler recycler)
        {
            if (slot == null || recycler == null || config.MaxPerTick <= 0) return null;

            ulong ownerId = recycler.OwnerID;
            if (ownerId != 0 && permission.UserHasPermission(ownerId.ToString(), PermBypass)) return null;

            if (amount <= config.MaxPerTick) return null;

            return config.MaxPerTick;
        }

        [ConsoleCommand("recycleramountlimit.reload")]
        private void CcmdReload(ConsoleSystem.Arg arg)
        {
            if (!arg.IsAdmin) return;

            LoadConfig();
            arg.ReplyWith(Msg("Reloaded", null, config.MaxPerTick));
        }
    }
}

The plugin clamps the number of items the recycler consumes per stack per tick to a configurable maximum, which slows down scrap farming on servers that want recycling to cost more time. OnItemRecycleAmount clamps the incoming amount and returns it as an int when it changed, otherwise returns null so the vanilla value is left alone. A permission (recycleramountlimit.bypass) exempts staff, and the plugin checks permission.UserHasPermission against the recycler's OwnerID before clamping. Config exposes the cap and the bypass permission string; LoadDefaultMessages holds the single chat message used when an admin reloads the plugin.

Common use cases

  • Rate-limit recycling

    Cap the per-tick consume amount so large batches of components recycle slowly, spreading scrap income over time on economy servers.

  • Permission-based speed

    Let VIPs recycle at the vanilla speed while regular players are clamped, by checking their user ID against the recycler's owner.

  • Debug scrap math

    Read slot.info.Blueprint.scrapFromRecycle and the computed amount to understand why a particular item yields more or less scrap than expected.

Pitfalls

  • Runs every tick

    A busy recycler can call this hook many times per second. Keep the body to a couple of comparisons; no string building, no Puts, no inventory lookups unless cached.

  • Not a cancel hook

    Changing the amount does not stop the stack from being consumed and does not change the scrap formula. To block recycling entirely return a non-null value from OnItemRecycle.

  • Owner is not a player

    Recycler.OwnerID is often 0 for map-placed recyclers, so permission checks based on it will fail unless you store ownership yourself.

Plugin recipes that use OnItemRecycleAmount

Build a plugin with OnItemRecycleAmount

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Rate-limit recycling using the OnItemRecycleAmount hook, with a config file and a permission
Generate this plugin

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 OnItemRecycleAmount

Generate