Skip to content
RustPluginGenerator

CanAccessVendingMachine

CanAccessVendingMachine is called while a MarketTerminal builds its list of vending machines that delivery drones may visit, once for each candidate machine. Returning a bool overrides whether that machine is treated as eligible.

Signature
object CanAccessVendingMachine(DeliveryDroneConfig config, VendingMachine vendingMachine)

Parameters

Hook parameters
ParameterTypeDescription
configDeliveryDroneConfigThe DeliveryDroneConfig for the vending machine being evaluated. Useful when you want to read per-machine delivery settings, though most access filters only need the VendingMachine itself.
vendingMachineVendingMachineThe VendingMachine entity the terminal is checking. Inspect its position, owner, or shop name to decide whether it should be reachable by delivery drones.

Return value

Return null (or any non-bool value) to let the game's normal eligibility logic decide. Return a bool to force the result for that machine: true marks it delivery-eligible, false excludes it, and the engine's own checks are skipped.

How it works

This hook fires inside the MarketTerminal eligibility check that assembles the set of vending machines a delivery drone can fly to. For every candidate VendingMachine passed to IsEligible, Oxide calls CanAccessVendingMachine with the machine and its DeliveryDroneConfig, before the game's own deep-sea and distance rules run.

The vendingMachine parameter gives you the entity to filter on: its transform.position, OwnerID, shopName, or its containers. The config parameter carries the delivery settings for that machine. Because the return value is checked first, a bool result is used directly as the eligibility answer, skipping the remaining engine checks for that machine.

You can narrow by declaring the machine as a more specific type, but the argument is always a VendingMachine, so BaseNetworkable or BaseEntity also match while unrelated types would be skipped. Keep the hook light: it can run many times while a terminal refreshes its machine list, so avoid heavy work or logging here.

Example plugin: Whitelist vending machines by map zone

VendingDeliveryWhitelist.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("VendingDeliveryWhitelist", "RustPluginGenerator", "1.0.0")]
    [Description("Limits which vending machines delivery drones may reach using configurable map zones.")]
    public class VendingDeliveryWhitelist : RustPlugin
    {
        private const string PermManage = "vendingdeliverywhitelist.zone";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Allowed zones (leave empty for all machines)")]
            public List<Zone> Zones = new List<Zone>();
        }

        private class Zone
        {
            [JsonProperty("Center X")]
            public float X;

            [JsonProperty("Center Z")]
            public float Z;

            [JsonProperty("Radius")]
            public float Radius = 50f;
        }

        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>
            {
                ["Added"] = "Added zone at {0} with radius {1} ({2} total).",
                ["Cleared"] = "Cleared all zones; every machine is delivery-eligible.",
                ["List_Empty"] = "No zones configured; all machines are delivery-eligible.",
                ["List_Header"] = "Configured zones:",
                ["List_Item"] = "{0}. {1} radius {2}",
                ["NoPermission"] = "You do not have permission to manage zones."
            }, 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(PermManage, this);
        }

        private object CanAccessVendingMachine(DeliveryDroneConfig deliveryConfig, VendingMachine vendingMachine)
        {
            if (vendingMachine == null) return null;
            if (config.Zones == null || config.Zones.Count == 0) return null;

            Vector3 pos = vendingMachine.transform.position;
            for (int i = 0; i < config.Zones.Count; i++)
            {
                Zone zone = config.Zones[i];
                if (zone == null) continue;
                float dx = pos.x - zone.X;
                float dz = pos.z - zone.Z;
                if (dx * dx + dz * dz <= zone.Radius * zone.Radius) return true;
            }
            return false;
        }

        [ChatCommand("vendingdeliverywhitelist.zone")]
        private void CmdZone(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermManage))
            {
                SendReply(player, Msg("NoPermission", player.UserIDString));
                return;
            }

            if (args == null || args.Length == 0)
            {
                SendReply(player, Msg("List_Header", player.UserIDString));
                for (int i = 0; i < config.Zones.Count; i++)
                {
                    Zone z = config.Zones[i];
                    SendReply(player, Msg("List_Item", player.UserIDString, i + 1, new Vector3(z.X, 0, z.Z).ToString("0"), z.Radius.ToString("0")));
                }
                if (config.Zones.Count == 0) SendReply(player, Msg("List_Empty", player.UserIDString));
                return;
            }

            if (args[0].ToLower() == "clear")
            {
                config.Zones.Clear();
                SaveConfig();
                SendReply(player, Msg("Cleared", player.UserIDString));
                return;
            }

            float radius = 50f;
            if (args.Length > 1 && !float.TryParse(args[1], out radius)) radius = 50f;

            Vector3 p = player.transform.position;
            config.Zones.Add(new Zone { X = p.x, Z = p.z, Radius = radius });
            SaveConfig();
            SendReply(player, Msg("Added", player.UserIDString, new Vector3(p.x, 0, p.z).ToString("0"), radius.ToString("0"), config.Zones.Count));
        }
    }
}

The plugin keeps a configurable list of allowed map zones (team, monument, or an empty list meaning all). CanAccessVendingMachine reads the machine's world position and compares it against each configured zone. If the position falls inside any allowed zone it returns true, so drones can reach that machine even if the engine might otherwise skip it; if no zones are configured it returns null to preserve vanilla behavior. The VendingDeliveryWhitelist.zone chat command lets admins add, list, or clear zones with a given radius, and the settings persist through the standard config file.

Common use cases

  • Restrict drones to safe zones

    Only allow delivery drones to reach machines inside a designated safe area by checking the machine position against that zone and returning false elsewhere.

  • Exclude unowned or admin shops

    Return false for machines whose OwnerID is 0 or that belong to admin-owned entities so players cannot route delivery to staff shops.

  • Manual override for reward shops

    Force true for specific machines used as event or reward shops, ensuring they stay delivery-eligible regardless of the engine's default filters.

Pitfalls

  • Fires per candidate machine

    The hook runs once for every machine the terminal evaluates, so it can be called many times during a refresh cycle. Keep the checks cheap and avoid PrintWarning or database writes inside it.

  • Returning a non-bool has no effect

    Only a bool return value changes behavior. Returning a bool for every machine overrides the engine entirely, so make sure your fallback path returns null when you do not mean to decide.

  • Delivery eligibility is not shop access

    This hook only affects whether delivery drones may visit the machine. It does not gate opening the shop or buying items, which are handled by other vending hooks.

Build a plugin with CanAccessVendingMachine

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

Prompt: Restrict drones to safe zones using the CanAccessVendingMachine 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 CanAccessVendingMachine

Generate