Skip to content
RustPluginGenerator

OnDeleteVendingOffer

OnDeleteVendingOffer is called when an admin removes a sell order from a vending machine, before the order is actually removed from the list.

Signature
void OnDeleteVendingOffer(VendingMachine vendingMachine, int num)

Parameters

Hook parameters
ParameterTypeDescription
vendingMachineVendingMachineThe VendingMachine entity the admin is editing. Use it to read its net.ID, position or current sellOrders list before the offer is removed.
numintThe 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

VendingOfferAudit.cs
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 num against the sell order count. Always confirm num >= 0 and num < sellOrders.sellOrders.Count before 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.sellOrders and null-check both the container and its sellOrders field before touching itemToSellID or other protobuf members.

Build a plugin with OnDeleteVendingOffer

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

Prompt: Admin audit trail using the OnDeleteVendingOffer 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 OnDeleteVendingOffer

Generate