Skip to content
RustPluginGenerator

CanRecycle

CanRecycle is called from Recycler.HasRecyclable for each of the recycler's first six inventory slots, allowing a plugin to override whether that item counts as recyclable. Returning a bool forces the result and short-circuits the game's own check.

Signature
object CanRecycle(Recycler recycler, Item slot)

Parameters

Hook parameters
ParameterTypeDescription
recyclerRecyclerThe Recycler entity whose inventory slots are being checked. Use it to inspect the recycler's position, owner or nearby players.
slotItemThe Item currently sitting in one of the recycler's first six inventory slots. It can be null when a slot is empty, so always null-check before reading item.info.

Return value

Return null (or any non-bool) to leave the vanilla CanBeRecycled check in control. Return a bool to force that slot's outcome: true makes HasRecyclable return true immediately, false skips the slot and lets the loop continue to the next one.

How it works

This hook fires inside Recycler.HasRecyclable, which loops over the recycler's first six slots. For every slot it passes the Recycler and the Item (or null for an empty slot) to Oxide. The game uses the boolean result of each iteration to decide whether the recycler should show as having something to process.

Returning a bool from your hook replaces the game's per-slot answer and stops that iteration immediately, so the built-in CanBeRecycled check is skipped for that item. Returning null lets the vanilla logic run: the item must exist in the recycler's recycle table to count. Because the loop returns on the first positive answer, your hook is effectively asked "can anything here be recycled?" slot by slot.

You cannot narrow the parameter types usefully here — recycler is always a Recycler and slot is an Item or null — but you can inspect slot.info.shortname, slot.amount, or the recycler's owner and position to build your own rules. Keep the method fast; it runs frequently for lootable recyclers near players, so avoid heavy loops or database-style lookups.

Example plugin: Block recycling of an item shortname list

RecycleBlacklist.cs
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Recycle Blacklist", "RustPluginGenerator", "1.0.0")]
    [Description("Prevents configured item shortnames from being counted as recyclable at recyclers")]
    public class RecycleBlacklist : RustPlugin
    {
        private const string PermManage = "recycleblacklist.manage";

        private PluginConfig config;
        private HashSet<string> blocked;

        private class PluginConfig
        {
            [JsonProperty("Blocked shortnames")]
            public List<string> BlockedShortnames = new List<string> { "rifle.ak", "rifle.lr300", "metal.refined" };
        }

        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();
            RebuildSet();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Added"] = "{0} is now blocked from recycling.",
                ["Removed"] = "{0} is no longer blocked from recycling.",
                ["NoPerm"] = "You do not have permission to manage the recycle blacklist."
            }, 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(PermManage, this);
        }

        private void RebuildSet()
        {
            blocked = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
            if (config.BlockedShortnames == null) return;
            foreach (var name in config.BlockedShortnames)
            {
                if (!string.IsNullOrEmpty(name)) blocked.Add(name);
            }
        }

        private object CanRecycle(Recycler recycler, Item slot)
        {
            if (slot == null || slot.info == null) return null;
            if (blocked != null && blocked.Contains(slot.info.shortname)) return false;
            return null;
        }

        [ChatCommand("recyclebl")]
        private void CmdRecycleBlacklist(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermManage))
            {
                player.ChatMessage(Msg("NoPerm", player.UserIDString));
                return;
            }
            if (args == null || args.Length == 0)
            {
                player.ChatMessage("Usage: /recyclebl <shortname>");
                return;
            }

            var shortname = args[0].ToLowerInvariant();
            if (ItemManager.FindItemDefinition(shortname) == null)
            {
                player.ChatMessage("Unknown item shortname: " + shortname);
                return;
            }

            if (blocked.Contains(shortname))
            {
                blocked.Remove(shortname);
                config.BlockedShortnames.Remove(shortname);
                player.ChatMessage(Msg("Removed", player.UserIDString, shortname));
            }
            else
            {
                blocked.Add(shortname);
                config.BlockedShortnames.Add(shortname);
                player.ChatMessage(Msg("Added", player.UserIDString, shortname));
            }
            SaveConfig();
        }
    }
}

The plugin reads a blacklist of shortnames from its config. CanRecycle runs for every slot the recycler checks; if the slot holds a blacklisted item it returns false so the vanilla path is skipped and the item never counts as recyclable. All other slots return null, letting the game's own recycle table decide. Admins toggle rules with a chat command rather than editing the file, and the list is saved to oxide/config on change. Because the hook fires often, it only does a small dictionary lookup per call and never prints to the console during normal operation.

Common use cases

  • Protect valuable items from auto-recyclers

    Block recyclers from hoovering up components like rifle bodies or tech trash that players store in recycler-adjacent boxes.

  • Event or zone-specific recycler rules

    Allow extra recycling only at a designated recycler by comparing recycler.transform.position to a configured radius, returning true for whitelisted items there.

  • Server economy gating

    Combine with a permission check on the recycler's owner so only VIPs can recycle certain item categories, denying the rest with a false return.

Pitfalls

  • Returning false for every slot

    If your hook returns false for all items the recycler will never report recyclable contents, and players cannot start recycling at all. Make sure unrecognised items fall through by returning null.

  • Null slots

    slot is null for empty slots in the first six positions. Reading slot.info without a check throws and can break the recycler's check loop.

  • Only the first six slots

    The hook only inspects the recycler's own inventory slots, not a player's backpack. Rules about player inventory must be enforced elsewhere.

Build a plugin with CanRecycle

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

Prompt: Protect valuable items from auto-recyclers using the CanRecycle 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 CanRecycle

Generate