Skip to content
RustPluginGenerator

OnShopCancelClick

OnShopCancelClick is called when a player clicks the cancel button on a vending machine trade window, before the trade is reset.

Signature
object OnShopCancelClick(ShopFront shopFront, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
shopFrontShopFrontThe ShopFront entity whose cancel button was clicked. Use it to read position, owner, or related vendor/customer state.
playerBasePlayerThe BasePlayer who clicked cancel. Only players actually trading with this shop front reach the hook.

Return value

Return null to let the trade reset as normal. Returning any non-null value cancels the reset, leaving the shop front still linked to the trading player, which can block that player from cleanly reopening a trade until it resets another way.

How it works

The hook fires inside ShopFront.CancelClicked, which the game runs when a client sends the cancel RPC for an active vending machine trade. The check IsTradingPlayer(msg.player) runs first, so only the player currently trading with that shop front triggers the hook; clicks from other players never reach it. shopFront is the vending machine entity, and player is the customer who requested the cancel. Both can be null-guarded but should normally be valid. Returning a non-null value stops the trade reset, so the shop front stays in its current trade state instead of clearing the vendor and customer references. Declaring BasePlayer keeps dispatch precise; the game always passes a real player here, so you do not need a narrower type. Typical uses are logging abandoned trades, charging a cancel fee, or notifying the shop owner that a sale fell through. Keep the callback cheap since it runs on a network message.

Example plugin: Log cancelled vending machine trades to chat

ShopCancelLogger.cs
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("ShopCancelLogger", "RustPluginGenerator", "1.0.0")]
    [Description("Notifies staff when a player cancels a vending machine trade")]
    public class ShopCancelLogger : RustPlugin
    {
        private const string PermNotify = "shopcancellogger.notify";

        private void Init()
        {
            permission.RegisterPermission(PermNotify, this);
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Cancel"] = "{0} cancelled a trade at {1}"
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
        {
            return string.Format(lang.GetMessage(key, this, userId), args);
        }

        private object OnShopCancelClick(ShopFront shopFront, BasePlayer player)
        {
            if (shopFront == null || player == null)
            {
                return null;
            }

            Vector3 pos = shopFront.transform.position;
            string position = string.Format("({0:0}, {1:0})", pos.x, pos.z);

            foreach (BasePlayer target in BasePlayer.activePlayerList)
            {
                if (target == null || target.IsNpc)
                {
                    continue;
                }

                if (!permission.UserHasPermission(target.UserIDString, PermNotify))
                {
                    continue;
                }

                target.ChatMessage(Msg("Cancel", target.UserIDString, player.displayName, position));
            }

            return null;
        }
    }
}

The plugin registers only the permission shopcancellogger.notify, which staff hold to receive cancel reports. When OnShopCancelClick fires, it builds a short message naming the player that cancelled and the shop front position, then iterates BasePlayer.activePlayerList, passing each player's UserIDString to permission.UserHasPermission. Matching players get a chat reply through the language file. The hook always returns null so the game still resets the trade. Null checks on shopFront and player guard against unexpected calls, and no logging happens when nobody holds the permission, keeping the callback light.

Common use cases

  • Track abandoned trades

    Record which players cancel vending machine trades and how often, to spot players probing shops for stock or exploiting trade windows.

  • Charge a cancel fee

    Read the player's balance through an Economy plugin reference and withdraw a small fee on cancel, returning null so the trade still closes.

  • Alert the shop owner

    Find the shop front's owner and send them a chat note when a customer cancels an in-progress trade.

Pitfalls

  • Returning a value blocks the reset

    Any non-null return leaves the shop front mid-trade. If you only want to observe the cancel, return null explicitly or simply fall through.

  • Only the trading player fires it

    Clicks from players not currently trading with that shop front are filtered before the hook, so you cannot use it to detect general shop front interaction.

  • Runs on an RPC

    The hook is invoked from network message handling, so avoid heavy work and never print warnings here; defer expensive logic to a timer if needed.

Build a plugin with OnShopCancelClick

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

Prompt: Track abandoned trades using the OnShopCancelClick 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 OnShopCancelClick

Generate