Skip to content
RustPluginGenerator

CanResearchItem

CanResearchItem is called when a player starts a research attempt at a ResearchTable, before the target item is consumed. Returning a non-null value cancels the research.

Signature
object CanResearchItem(BasePlayer player, Item targetItem)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer using the research table. Always non-null at this call site since ResearchTable.DoResearch only runs for a real user.
targetItemItemThe Item currently placed in the research table that is about to be consumed for research. Check info, amount, skin and condition to decide whether the research is allowed.

Return value

Return null to let the research proceed normally. Return any non-null value (for example true) to stop the research; the item is not consumed, no timer starts, and OnItemResearch is never called. The method returns void, so the returned value itself is not used by the game.

How it works

The hook fires inside ResearchTable.DoResearch, which is triggered when a player activates the research action on a table with a target item placed. It runs after the target item has been resolved and before any of the research work happens: the item is not yet collected for crafting, the research timer has not started, and OnItemResearch has not fired. Because of that, cancelling here leaves the item untouched and the player simply sees nothing happen.

Use targetItem to inspect info.shortname, amount, skin or condition. The game itself only proceeds when the item has amount <= 1 and passes its own IsItemResearchable check, so you do not need to repeat those validations; your decision is layered on top. Use player for permission checks, per-player limits or economy lookups.

There is only one call site, so declaring the exact BasePlayer and Item types is correct. If you narrow player to a subtype it will not match here and your hook will never run.

Example plugin: Charge scrap to allow research

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

namespace Oxide.Plugins
{
    [Info("Research Fee", "RustPluginGenerator", "1.0.0")]
    [Description("Charges scrap before a player can research an item at a research table.")]
    public class ResearchFee : RustPlugin
    {
        private const string PermBypass = "researchfee.bypass";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Scrap cost per research")]
            public int ScrapCost = 10;

            [JsonProperty("Bypass permission")]
            public string BypassPermission = PermBypass;
        }

        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>
            {
                ["NotEnoughScrap"] = "You need {0} scrap to research this item.",
                ["Charged"] = "Research fee of {0} scrap taken."
            }, 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(config.BypassPermission, this);
        }

        private object CanResearchItem(BasePlayer player, Item targetItem)
        {
            if (player == null || targetItem == null || targetItem.info == null)
                return null;

            if (config.ScrapCost <= 0)
                return null;

            if (permission.UserHasPermission(player.UserIDString, config.BypassPermission))
                return null;

            var scrapDef = ItemManager.FindItemDefinition("scrap");
            if (scrapDef == null)
                return null;

            if (player.inventory.GetAmount(scrapDef.itemid) < config.ScrapCost)
            {
                player.ChatMessage(Msg("NotEnoughScrap", player.UserIDString, config.ScrapCost));
                return true;
            }

            var taken = player.inventory.Take(null, scrapDef.itemid, config.ScrapCost);
            if (taken <= 0)
            {
                player.ChatMessage(Msg("NotEnoughScrap", player.UserIDString, config.ScrapCost));
                return true;
            }

            player.ChatMessage(Msg("Charged", player.UserIDString, taken));
            return null;
        }
    }
}

The plugin makes research cost a configurable amount of scrap in addition to the normal recipe requirement. In CanResearchItem it checks a permission bypass first, then the player's main inventory for the configured scrap amount. If the player cannot pay, the hook returns true to abort the research and sends a localized chat message. If they can pay, the scrap is taken with inventory.Take and null is returned so the game continues normally. Config exposes both the price and the bypass permission, which is registered in Init.

Common use cases

  • Restrict research by permission

    Only allow owners of a 'vip' permission to research certain items, blocking the rest with a message pointing them at the server store.

  • Add a resource cost

    Require scrap or another resource before research starts; take it in the hook and cancel the attempt when the player lacks it.

  • Per-player daily limits

    Track research counts per player in oxide/data and refuse further research after a configured cap resets each day.

Pitfalls

  • The item amount is already validated

    DoResearch only reaches this hook when the target item has amount 1 or less and passes IsItemResearchable. Do not try to block stacked or unresearchable items here; they never get here.

  • The return value is ignored, only non-null matters

    This is a void method, so returning true or false has the same cancel effect and returning false does not allow anything that would otherwise be blocked. Always return null to permit.

  • Take resources before returning null

    If you charge a resource, take it inside the hook only when you are about to allow research. Charging after the fact is impossible because no later valid hook reports success here.

Build a plugin with CanResearchItem

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

Prompt: Restrict research by permission using the CanResearchItem 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 CanResearchItem

Generate