OnDeleteVendingOffer
OnDeleteVendingOffer is called when an admin removes a sell order from a vending machine, before the order is actually removed from the list.
void OnDeleteVendingOffer(VendingMachine vendingMachine, int num)Parameters
| Parameter | Type | Description |
|---|---|---|
vendingMachine | VendingMachine | The VendingMachine entity the admin is editing. Use it to read its net.ID, position or current sellOrders list before the offer is removed. |
num | int | The zero-based index of the sell order being deleted in vendingMachine.sellOrders.sellOrders. It is read from the client RPC and is not validated yet when the hook fires. |
Return value
The return value is ignored. The original method continues and removes the sell order at the given index, so returning true, false or null has no effect on the deletion.
How it works
This hook fires inside VendingMachine.RPC_DeleteSellOrder, the server RPC the vending admin UI sends when someone clicks the delete button on an offer. The game first checks CanPlayerAdmin(player); only then does it read the order index and call the hook. The call happens before the bounds check, so num may be negative or past the end of vendingMachine.sellOrders.sellOrders — validate it yourself before indexing. vendingMachine is the machine being edited and is never null when the hook fires.
Because the hook has no return handling, it is purely observational on this code path: the removal proceeds right after the call. Use it to log admin activity, snapshot the offer that is about to disappear (item to sell, currency, amounts, BP flags), or notify staff. If you want to prevent or change deletions, do that from hooks that run earlier, such as CanAdministerVending, rather than here.
You can declare vendingMachine as a more specific type only if you are sure the argument matches; VendingMachine is already the exact type, so keep it.
Example plugin: Log deleted vending offers for admins
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Vending Offer Audit", "RustPluginGenerator", "1.0.0")]
[Description("Logs and broadcasts vending machine sell orders removed by admins.")]
public class VendingOfferAudit : RustPlugin
{
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Write to server log")]
public bool WriteToLog = true;
[JsonProperty("Notify online admins")]
public bool NotifyAdmins = 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>
{
["Deleted"] = "{0} removed offer #{1} from a vending machine: sell {2}x {3}, price {4}x {5}",
["Invalid"] = "{0} sent a delete request for invalid offer index {1} on a vending machine",
["AdminAlert"] = "Vending audit: {0}"
}, this);
}
private string Msg(string key, string userId = null, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
private void OnDeleteVendingOffer(VendingMachine vendingMachine, int index)
{
if (vendingMachine == null || vendingMachine.sellOrders == null) return;
BasePlayer admin = null;
var orders = vendingMachine.sellOrders.sellOrders;
string line;
if (index < 0 || index >= orders.Count)
{
line = Msg("Invalid", null, "An admin", index);
}
else
{
var order = orders[index];
string sellName = ShortName(order.itemToSellID);
string currencyName = ShortName(order.currencyID);
string sellLabel = order.itemToSellIsBP ? sellName + " (BP)" : sellName;
string currencyLabel = order.currencyIsBP ? currencyName + " (BP)" : currencyName;
line = Msg("Deleted", null, "An admin", index, order.itemToSellAmount, sellLabel,
order.currencyAmountPerItem, currencyLabel);
}
if (config.WriteToLog)
Puts(line);
if (!config.NotifyAdmins) return;
foreach (var player in BasePlayer.activePlayerList)
{
if (player == null || !player.IsConnected || !player.IsAdmin) continue;
player.ChatMessage(Msg("AdminAlert", player.UserIDString, line));
}
}
private static string ShortName(int itemId)
{
var def = ItemManager.FindItemDefinition(itemId);
return def != null ? def.shortname : itemId.ToString();
}
}
}The plugin records every sell order deleted from a vending machine and writes the entry to chat and to the server log so staff can audit shop changes. OnDeleteVendingOffer reads the machine's sellOrders.sellOrders list, verifies that num is within range (the hook fires before the game's own bounds check), and pulls the item shortnames, amounts and blueprint flags from the protobuf SellOrder into a readable message. Deletions that reference an invalid index are reported as a single warning line instead of being skipped silently. Everything is formatted through the language file, so admins can translate the audit text.
Common use cases
Admin audit trail
Log who is editing vending machines and which offers were removed so server staff can review shop changes after the fact.
Back up offer data before removal
Copy the sell order fields (item, amount, currency, blueprint flags) into your own data file so a deleted listing can be recreated later.
Alert online admins
Send a chat note to connected admins when any vending offer is deleted, which helps catch unauthorized edits on shops owned by other players.
Pitfalls
Index is not validated yet
The hook fires before the game checks
numagainst the sell order count. Always confirmnum >= 0andnum < sellOrders.sellOrders.Countbefore reading the order.You cannot cancel the deletion here
The return value is ignored on this path, so blocking removal requires a different approach, such as limiting admin access via
CanAdministerVending.sellOrders may be null
Read the list through
vendingMachine.sellOrdersand null-check both the container and itssellOrdersfield before touchingitemToSellIDor other protobuf members.
Build a plugin with OnDeleteVendingOffer
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 OnDeleteVendingOffer
Generate