Skip to content
RustPluginGenerator

OnBuildingPrivilege

OnBuildingPrivilege is called from BaseEntity.GetBuildingPrivilege whenever the game resolves which building privilege (tool cupboard) applies to an entity, and lets a plugin override the result.

Signature
object OnBuildingPrivilege(BaseEntity entity, OBB obb, bool cached, float cacheDuration, BuildingPrivlidge exclude, bool ignorePosition)

Parameters

Hook parameters
ParameterTypeDescription
entityBaseEntityThe BaseEntity whose building privilege is being resolved. Usually a player, a deployed deployable or a projectile asking whether it stands inside a cupboard zone.
obbOBBThe oriented bounding box used for the position test against each cupboard's privilege volume.
cachedboolTrue when the caller allows the cached privilege result to be reused; false forces a fresh computation.
cacheDurationfloatHow long, in seconds, a cached privilege lookup stays valid before it is recomputed.
excludeBuildingPrivlidgeA BuildingPrivlidge that must be ignored in the lookup, typically the cupboard itself when it is checking its own zone.
ignorePositionboolWhen true the position/OBB test is skipped, so the lookup does not depend on where the entity stands.

Return value

Return a BuildingPrivlidge to use that cupboard as the privilege result for this call. Returning null or any other type leaves the original method running, so the cached check and the regular OBB-based lookup produce the result.

How it works

The hook fires inside BaseEntity.GetBuildingPrivilege(OBB obb, bool cached, float cacheDuration, BuildingPrivlidge exclude, bool ignorePosition). That method is used all over the server: player build checks, deployable placement, damage and decay logic, raid protection tests and anything else that needs to know which cupboard governs a position. The hook receives the entity doing the query, the OBB used for the position test, the cache flags, the cupboard to exclude (often the cupboard performing its own check) and the ignorePosition flag.

Returning a BuildingPrivlidge replaces the game's answer. Returning null (or any other type) lets the original method run: the cached result, then the normal spatial lookup. You can narrow entity to a more specific type such as BasePlayer; Oxide then only calls your method when the argument really is that type, which lets you scope rules to players. Keep the method cheap because build, damage and decay code calls it frequently, and avoid Puts inside it.

Example plugin: Infinite upkeep privilege for a protected zone

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

namespace Oxide.Plugins
{
    [Info("Upkeep Zone Privilege", "RustPluginGenerator", "1.0.0")]
    [Description("Treats players standing near configured tool cupboards as privileged there.")]
    public class UpkeepZonePrivilege : RustPlugin
    {
        private const string PermUse = "upkeepzoneprivilege.use";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Enable plugin")]
            public bool Enabled = true;

            [JsonProperty("Only players with permission")]
            public bool RequirePermission = false;

            [JsonProperty("Cupboards and radius (cupboard name -> radius in metres)")]
            public Dictionary<string, float> Zones = new Dictionary<string, float>
            {
                ["shop_cupboard"] = 15f
            };
        }

        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);

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

        private object OnBuildingPrivilege(BaseEntity entity, OBB obb, bool cached, float cacheDuration, BuildingPrivlidge exclude, bool ignorePosition)
        {
            if (!config.Enabled || ignorePosition || entity == null) return null;

            var player = entity as BasePlayer;
            if (player == null || player.IsNpc) return null;
            if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse)) return null;

            Vector3 position = player.transform.position;

            foreach (var pair in config.Zones)
            {
                var cupboards = FindCupboard(pair.Key);
                for (int i = 0; i < cupboards.Count; i++)
                {
                    var cupboard = cupboards[i];
                    if (cupboard == null || cupboard == exclude || cupboard.IsDestroyed) continue;
                    if (Vector3.Distance(cupboard.transform.position, position) > pair.Value) continue;
                    return cupboard;
                }
            }

            return null;
        }

        private List<BuildingPrivlidge> FindCupboard(string shortname)
        {
            var result = new List<BuildingPrivlidge>();
            foreach (var networkable in BaseNetworkable.serverEntities)
            {
                var cupboard = networkable as BuildingPrivlidge;
                if (cupboard == null || cupboard.IsDestroyed) continue;
                if (cupboard.ShortPrefabName != shortname) continue;
                result.Add(cupboard);
            }
            return result;
        }
    }
}

The plugin keeps a list of cupboard names in its config. When the game looks up building privilege for a player, it compares the player's position to the configured cupboards and, if the player is within range, returns that cupboard so the game treats the player as authorized there.

OnBuildingPrivilege returns null for anything that is not a BasePlayer, so deployables, projectiles and NPCs behave normally. Because the player is genuinely authorized, the existing building and raid rules stay intact; only the cupboard match is widened. The example only runs when ignorePosition is false, since an ignore-position lookup is an administrative query rather than a real position test.

Common use cases

  • Granted build rights in a shop or event area

    Return a designated cupboard for players inside a radius so they can build without being added to the authorize list.

  • Custom raid protection

    Return null or a specific cupboard depending on your own rules so damage checks against the right privilege zone.

  • Per-player privilege overrides

    Narrow the entity parameter to BasePlayer and return a cupboard only for players meeting a permission or team check.

Pitfalls

  • This hook fires constantly

    Build, decay and damage code all call GetBuildingPrivilege. Keep the checks inside short and avoid chat messages or logging.

  • Returning the wrong type is ignored

    Only a BuildingPrivlidge return value takes effect. Returning true, a bool or an unrelated entity falls through to the original lookup.

  • Cached answers may skip your override

    If you return null, the game may reuse a cached privilege. Return a cupboard explicitly when you need a specific result every time.

Build a plugin with OnBuildingPrivilege

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

Prompt: Granted build rights in a shop or event area using the OnBuildingPrivilege 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 OnBuildingPrivilege

Generate