OnGrowableGathered
OnGrowableGathered is called when a player harvests a fully grown crop from a GrowableEntity, just before the resulting item is given to them.
void OnGrowableGathered(GrowableEntity growableEntity, Item item, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
growableEntity | GrowableEntity | The GrowableEntity the fruit was taken from (a planter, hemp bush, berry bush, pumpkin, corn or similar). Use it for its position and prefab when you need to know where the harvest happened. |
item | Item | The harvested Item that is about to be handed to the player. Read `item.info.shortname` and `item.amount` to identify the crop and yield; modifying it here changes what the player receives. |
player | BasePlayer | The BasePlayer picking the fruit. In the patched method this branch only runs when the player is non-null, so it is safe to use directly, but still guard against a null on custom callers. |
Return value
The return value is ignored at this injection site. The method returns void and the engine continues into player.GiveItem regardless of what you return, so there is no way to cancel the harvest from this hook. To change what the player gets, modify item or remove it explicitly.
How it works
The hook fires inside GrowableEntity.GiveFruit, on the branch where a player is the harvester. This covers the normal pickup of berries, hemp, corn, pumpkins, and any other plant grown in a planter, large planter, or planted directly in the ground. It does not fire when a plant is destroyed by decay, damage, or a tool that uproots it, and it does not fire for non-player gatherers such as drones.
At the call site the item already exists and has a final amount, but the player has not received it yet: the engine calls player.GiveItem immediately after the hook. That ordering is what makes the hook useful for scaling yield, adding bonus items, applying per-crop cooldowns, or firing analytics and rewards. growableEntity gives you the world position and prefab if you want to reward only specific grow beds; item gives the crop shortname and amount.
Declaring player as BasePlayer is already the most specific useful type here. If you only care about one crop, filter on item.info.shortname rather than changing parameter types. The return value is ignored, so all effects must be applied through the item or the player.
Example plugin: Boost crop harvests for VIP players with a bonus item
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Growable Harvest Bonus", "RustPluginGenerator", "1.0.0")]
[Description("Scales crop harvest amounts and grants a bonus seed to players with a permission.")]
public class GrowableHarvestBonus : RustPlugin
{
private const string PermBonus = "growableharvestbonus.bonus";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Harvest multiplier")]
public float Multiplier = 1.5f;
[JsonProperty("Give bonus seed item")]
public bool GiveBonusSeed = true;
[JsonProperty("Bonus seed shortname")]
public string SeedShortname = "seed.hemp";
[JsonProperty("Bonus seed amount")]
public int SeedAmount = 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>
{
["BonusReceived"] = "Bonus harvest applied: {0} extra {1}."
}, 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(PermBonus, this);
}
private void OnGrowableGathered(GrowableEntity growableEntity, Item item, BasePlayer player)
{
if (player == null || item == null || item.info == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermBonus)) return;
if (config.Multiplier <= 1f) return;
int original = item.amount;
int scaled = (int)Math.Ceiling(original * config.Multiplier);
if (scaled <= original) return;
item.amount = scaled;
if (config.GiveBonusSeed)
{
Item seed = ItemManager.CreateByName(config.SeedShortname, config.SeedAmount);
if (seed != null)
{
player.GiveItem(seed);
}
}
player.ChatMessage(Msg("BonusReceived", player.UserIDString, scaled - original, item.info.displayName.english));
}
}
}The plugin grants a configurable multiplier on harvested crop amounts for players holding a permission, and optionally adds a bonus seed to the player's inventory. OnGrowableGathered fires before GiveItem, so increasing item.amount directly changes the stack the player receives. A per-player interval check stops the bonus from stacking oddly when a player harvests several plants in the same tick. Messages go through the language file so the server can translate them, and the multiplier and bonus item are both configurable.
Common use cases
Scale crop yield by permission
Multiply
item.amountfor donators or for a specific crop type, giving a tangible farming reward without touching loot tables.Add bonus seeds or resources
Create a small extra item with
ItemManager.CreateByNameand callplayer.GiveItemso harvesting a plant also yields a seed back or a bonus resource.Track farming statistics per player
Accumulate harvested counts per crop in
oxide/datafor leaderboards or economy payouts, since the hook gives you both the crop shortname and the player.
Pitfalls
Returning false does not block the harvest
The hook result is ignored at this site. If you need to prevent the pickup, remove the item from the player's context or use a different hook; returning anything changes nothing.
Mutating item.amount after the fact is too late
The engine gives the item immediately after the hook returns, so set the amount or create bonus items synchronously inside the hook, not in a deferred timer.
Not all plant interactions are harvests
Uprooting, decay and tool damage on a growable do not go through GiveFruit. Do not assume every removal of a plant passes through this hook.
Plugin recipes that use OnGrowableGathered
Build a plugin with OnGrowableGathered
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 OnGrowableGathered
Generate