Skip to content
RustPluginGenerator

OnShopAcceptClick

OnShopAcceptClick is called when a player clicks the action button in a vending machine's shop UI, before ShopFront runs its accept logic. Returning a non-null value cancels the click.

Signature
object OnShopAcceptClick(ShopFront shopFront, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
shopFrontShopFrontThe ShopFront entity the player is interacting with. Use it to read the vendor and customer players, the attached vending machine, and its position.
playerBasePlayerThe BasePlayer who pressed the accept/action button on the shop UI. This is the player whose click OpenLoot/accept RPC arrived for.

Return value

Returning null (or falling off the end) lets the shop proceed with its normal accept logic. Returning any non-null object, including a plain string or true, aborts the click so the trade does not advance.

How it works

The hook fires inside ShopFront.AcceptClicked(RPCMessage msg) as the first check of the method. The RPC is sent when a player presses the confirm/accept control in the shop interface of a vending machine or player shop. Before any flags are set or any trade state changes, Oxide calls OnShopAcceptClick with the ShopFront and the clicking BasePlayer.

The game already filters out clients that are not trading players, and shops that have no assigned vendor or customer; your hook is only invoked past that guard. msg.player is passed as the player argument, so it is always a connected player who owns the RPC.

Because the injection only checks that a non-null value is returned, the exact return value does not matter: anything other than null stops the original code path. Use it to refuse clicks for reasons of your own (permission, cooldown, blacklist, anti-abuse), then show the player why. Declaring the parameter as ShopFront is required; narrowing it further makes no sense since the type is already concrete. BasePlayer in place of a derived type is fine.

The hook fires on every accept click, so avoid logging or any heavy work in it.

Example plugin: Require permission to confirm shop purchases

ShopClickPermission.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Shop Click Permission", "RustPluginGenerator", "1.0.0")]
    [Description("Requires a permission before a player can confirm a vending machine purchase.")]
    public class ShopClickPermission : RustPlugin
    {
        private const string PermUse = "shopclickpermission.use";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Require permission to accept shop trades")]
            public bool RequirePermission { get; set; } = true;

            [JsonProperty("Block mounted players")]
            public bool BlockMounted { 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 do not have permission to confirm shop trades.",
                ["Mounted"] = "Dismount before confirming a shop trade."
            }, 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 OnShopAcceptClick(ShopFront shopFront, BasePlayer player)
        {
            if (shopFront == null || player == null || !player.IsConnected)
                return null;

            if (config.BlockMounted && player.isMounted)
            {
                player.ChatMessage(Msg("Mounted", player.UserIDString));
                return "mounted";
            }

            if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse))
            {
                player.ChatMessage(Msg("NoPermission", player.UserIDString));
                return "no_permission";
            }

            return null;
        }
    }
}

The plugin registers a permission (shopclickpermission.use) and lets players with it confirm a vending machine transaction as usual. In OnShopAcceptClick it reads the clicking player, checks the permission, and returns a non-null value when the player lacks it, which cancels the accept before the shop mutates any state. The denied player gets a localized chat message; the check is silent for allowed players so a busy server does not spam chat or logs. Everything the player sees goes through the language file, so admins can reword it. Unload is empty apart from the standard cleanup nothing persistent is stored.

Common use cases

  • Gate purchases behind a permission

    Only players with a specific permission (VIP, whitelist, event participant) may confirm shop transactions; others have the click cancelled and are told why.

  • Temporary shop lockdown

    Flip a config flag during events or wipes to refuse all accept clicks on shop fronts, then re-enable without restarting the server.

  • Anti-abuse checks

    Refuse confirmations from players who are mounted, wounded, or inside a blocked building to cut down on vending machine scams in restricted zones.

Pitfalls

  • Returning null is not 'deny'

    The hook only cancels when you return something. If your permission check fails, return a non-null value (a string is fine); returning null lets the trade through.

  • Do not mutate the shop inside the hook

    Cancelling the click does not undo anything, and touching the shop front's internals from here can leave the UI out of sync. Do side effects from a follow-up hook like OnShopCompleteTrade instead.

  • Fires on every click

    The hook runs for each accept press on every shop front. Keep it to cheap permission/config lookups and never PrintWarning or write data here.

Build a plugin with OnShopAcceptClick

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

Prompt: Gate purchases behind a permission using the OnShopAcceptClick 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 OnShopAcceptClick

Generate