OnBuyVendingItem
OnBuyVendingItem is called when a player confirms a purchase on a VendingMachine, before the server moves currency and sold items. Returning a non-null value aborts the purchase.
object OnBuyVendingItem(VendingMachine vendingMachine, BasePlayer player, int orderIndex, int amount)Parameters
| Parameter | Type | Description |
|---|---|---|
vendingMachine | VendingMachine | The VendingMachine entity the player is buying from. Use it to read sellOrders, the machine's position or OwnerID to apply per-machine rules. |
player | BasePlayer | The BasePlayer who triggered the purchase RPC. This is the buyer, not necessarily the machine owner. |
orderIndex | int | Index of the sell order the player clicked in the shop UI (num in the decompiled method). Use it to look up vendingMachine.sellOrders.sellOrders[orderIndex]. |
amount | int | Number of items the player requested in the purchase RPC (num2 in the decompiled method). This value comes from the client and is validated by the game afterwards. |
Return value
Return null to let the purchase proceed normally. Returning any non-null value (commonly true) makes BuyItem return immediately, so no currency is taken and no items are handed out.
How it works
The hook fires inside VendingMachine.BuyItem, after the vending machine has checked that it is not busy and after the wait-for-vending toast, but before the sell orders are iterated and stock is consumed. Any RPC that reaches BuyItem triggers it: a normal buy from the shop UI and the matching buy path used by vending machines. vendingMachine gives you the machine, its sellOrders list and OwnerID; player is the buyer; the order index and requested amount let you resolve which ProtoBuf.VendingMachine.SellOrder is being bought and check currencyItem.amount * amount type math before the game does. Because a non-null return stops BuyItem before it touches inventory, this is the place to refuse purchases (blocked shop, blacklisted item, insufficient custom currency, event restriction) without the player losing anything. Declaring vendingMachine as a more specific type does not help here since the game always passes a VendingMachine; narrowing only makes sense if you plan to extend the hook to vendors of a subclass. Prefer CanPurchaseItem for per-item checks if you only need a yes/no gate, since it fires earlier in the flow.
Example plugin: Restrict vending machine sales to a permission group
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("VendingPurchaseGate", "RustPluginGenerator", "1.0.0")]
[Description("Blocks vending machine purchases for players without a permission, optionally excluding machine owners")]
public class VendingPurchaseGate : RustPlugin
{
private const string PermUse = "vendingpurchasegate.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Allow machine owners to always buy")]
public bool AllowOwners { get; set; } = true;
}
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>
{
["NoPermission"] = "You are not allowed to buy from vending machines.",
["OwnerAllowed"] = "Owners can always buy from their own machine."
}, 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 OnBuyVendingItem(VendingMachine vendingMachine, BasePlayer player, int orderIndex, int amount)
{
if (vendingMachine == null || player == null) return null;
if (permission.UserHasPermission(player.UserIDString, PermUse)) return null;
if (config.AllowOwners && vendingMachine.OwnerID == player.userID.Get()) return null;
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return true;
}
}
}The plugin registers a single permission and checks it in OnBuyVendingItem. Players without vendingpurchasegate.use are refused, told why through a localized message and the purchase is cancelled. Optionally, a config flag limits the gate to machines the buyer does not own, so owners can still test their shop. Because the hook returns before the game reads currency, a denied player keeps their scrap and items and the machine stock is untouched. All feedback goes through the language file so the text can be translated or edited without recompiling.
Common use cases
Custom currency gates
Refuse or allow a purchase based on a referenced economy plugin, a cooldown or a per-player daily limit before any scrap leaves the buyer's inventory.
Item blacklists per machine
Look up the clicked sell order and block sales of specific shortnames on selected vending machines, for example on event arenas or roleplay hubs.
Purchase logging and auditing
Record the buyer, order index, amount and machine position for later review, then return null so the sale completes normally.
Pitfalls
Returning false still cancels
The patch treats any non-null return as a cancel. Returning
falsefrom the hook aborts the purchase just liketrue; onlynulllets it through.Amount is client supplied
The requested amount arrives from the client RPC. Trust it only for early rejection logic and let the game's own validation run by returning null when you do not want to block.
Not every buy goes through here
Machines that were emptied or configurations using other purchase paths may not reach
BuyItem. Pair this hook withCanPurchaseItemif your rule must hold in all cases.
Build a plugin with OnBuyVendingItem
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 OnBuyVendingItem
Generate