OnDispenserGather
OnDispenserGather is called from ResourceDispenser.GiveResourceFromItem right after the gathered Item is created and before it is applied to the player.
object OnDispenserGather(ResourceDispenser resourceDispenser, BasePlayer entity, Item item)Parameters
| Parameter | Type | Description |
|---|---|---|
resourceDispenser | ResourceDispenser | The ResourceDispenser entity that produced the resource, usually a tree, ore node or corpse with a dispenser component. Use it to read transform.position or net.ID for per-node logic. |
entity | BasePlayer | The BasePlayer who hit the dispenser. Null-check it and its connection before sending UI or chat; NPCs can also trigger gather logic in some setups. |
item | Item | The freshly created Item that is about to be given to the player, already scaled by gather rate and bonus. Changing item.amount or item.skin here affects what the player receives. |
Return value
Returning null lets the original code continue: the item is given ownership, analytics fire and OnDispenserGathered is invoked. Returning any non-null object stops that path, so the item is never applied to the player and no OnDispenserGathered follows.
How it works
The hook fires inside ResourceDispenser.GiveResourceFromItem, the method that turns one hit on a tree, ore node or similar dispenser into an item. By the time it runs, the gather amount has already been calculated from the tool, the node's health fraction and gather bonuses, and an Item has been instantiated but not yet handed to the player.
The resourceDispenser parameter identifies the node, useful for per-prefab rules such as different multipliers for stones versus sulfur nodes. entity is the gathering player, and item is the item instance about to be awarded. Adjusting item.amount, item.skin or even swapping item.info-driven values lets you shape the reward without touching the tool or the node.
Declaring entity as a more specific type than BasePlayer narrows dispatch: Oxide only calls your method when the argument matches the declared type, so a too-specific parameter silently skips calls. Returning a non-null value stops the original code path, so the item is never applied to the player and no OnDispenserGathered call follows. That makes the return a veto, not a multiplier.
Example plugin: Boost ore gather amounts by node type
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Dispenser Gather Boost", "RustPluginGenerator", "1.0.0")]
[Description("Scales the amount of resources awarded from designated dispenser nodes.")]
public class DispenserGatherBoost : RustPlugin
{
private const string PermUse = "dispensergatherboost.use";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastNotice = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Gather multiplier by prefab name")]
public Dictionary<string, float> Multipliers = new Dictionary<string, float>
{
["ore_sulfur"] = 1.5f,
["ore_metal"] = 1.25f,
["ore_stone"] = 1.25f
};
[JsonProperty("Notify player on boosted gather")]
public bool NotifyPlayer = true;
[JsonProperty("Notice cooldown seconds")]
public float NoticeCooldown = 15f;
}
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>
{
["Boosted"] = "You gathered {0}x {1} (boosted)."
}, 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 object OnDispenserGather(ResourceDispenser resourceDispenser, BasePlayer entity, Item item)
{
if (resourceDispenser == null || entity == null || item == null) return null;
if (!permission.UserHasPermission(entity.UserIDString, PermUse)) return null;
BaseEntity baseEntity = resourceDispenser.GetComponent<BaseEntity>();
string prefab = baseEntity != null ? baseEntity.ShortPrefabName : null;
if (string.IsNullOrEmpty(prefab) || !config.Multipliers.TryGetValue(prefab, out float multiplier)) return null;
if (multiplier <= 1f) return null;
int baseAmount = item.amount;
int boosted = (int)Math.Ceiling(baseAmount * multiplier);
if (boosted <= baseAmount) return null;
item.amount = boosted;
if (config.NotifyPlayer && entity.IsConnected)
NotifyIfReady(entity, boosted - baseAmount, item.info.displayName.english);
return null;
}
private void NotifyIfReady(BasePlayer player, int extra, string resourceName)
{
float now = UnityEngine.Time.realtimeSinceStartup;
ulong userId = player.userID;
if (lastNotice.TryGetValue(userId, out float last) && now - last < config.NoticeCooldown) return;
lastNotice[userId] = now;
player.ChatMessage(Msg("Boosted", player.UserIDString, extra, resourceName));
}
private void Unload()
{
lastNotice.Clear();
}
}
}The plugin defines a config with a multiplier per short prefab name, a per-player notification toggle and a notice cooldown. When OnDispenserGather fires it reads the node's ShortPrefabName, checks the player has the dispensergatherboost.use permission, looks the prefab up in the configured dictionary and scales item.amount (rounded up) before the item is applied. Unknown prefabs, missing permission, or a multiplier of 1 or less return immediately, keeping default behavior. If notifications are enabled and the player is connected, a short chat notice showing the extra yield is sent, throttled per player by the configured cooldown so the chat is not flooded on every swing. Returning null keeps the normal award path intact. Changing the config and reloading the plugin is enough to retune the numbers.
Common use cases
Per-node gather multipliers
Scale
item.amountfor specific node prefabs to make sulfur or stone farming easier on a PvE server while leaving trees untouched.Event-only bonus resources
During a timed event, replace the gathered item with a rarer resource by manipulating
item.amountand the surrounding reward logic in your own code.Veto gathering for jailed players
Return a non-null value when the player is in a restricted zone or jail, blocking the item from being awarded while the node still takes damage.
Pitfalls
Non-null return blocks the whole award
Returning a value stops the award path entirely, including ownership and the
OnDispenserGatheredhook. Use it only when you want to suppress the gather, not to change it.item may be null in edge cases
Always null-check
itemandentitybefore touching their members; NPC or scripted dispenser calls can pass unexpected values.Fires on every swing
The hook runs for each gather tick, so avoid logging,
Putsor chat spam here. Throttle player notices or skip them entirely.
Plugin recipes that use OnDispenserGather
- How to make a Rust auto smelt on gather plugin (ore to fragments)Converts gathered metal ore into metal fragments, sulfur ore into sulfur and optionally wood into charcoal for players with a permission, using OnDispenserGather and OnDispenserBonus.
- How to make a Rust double gather event plugin (scheduled multiplier)Runs scheduled or admin-triggered double gather windows that multiply dispenser and collectible yields for a fixed duration, with start and end announcements. It uses OnDispenserGather and OnCollectiblePickup to scale item amounts.
- How to make a Rust gather bonus plugin (VIP tiers)Gives players with tiered permissions extra resources when they gather from nodes with a ResourceDispenser or pick up collectible entities, using OnDispenserGather and OnCollectiblePickup.
- How to make a Rust gather rate plugin (per-resource multipliers)Scales resources from trees, ore nodes, corpses and world pickups with per-resource multipliers and a VIP bonus. Uses OnDispenserGather, OnDispenserBonus and OnCollectiblePickup.
Build a plugin with OnDispenserGather
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 OnDispenserGather
Generate