Skip to content
RustPluginGenerator

OnRackedWeaponMounted

OnRackedWeaponMounted is called by WeaponRack.MountWeapon right after a weapon has been stored in a weapon rack and the rack has been networked to clients. It fires once per successful mount, before MountWeapon returns true.

Signature
void OnRackedWeaponMounted(Item item, BasePlayer player, WeaponRack weaponRack)

Parameters

Hook parameters
ParameterTypeDescription
itemItemThe weapon Item that was just stored in the rack. Use item.info.shortname for the weapon type, item.skin for skin checks and item.uid to track it. It is already inside the rack's storage container when the hook fires.
playerBasePlayerThe BasePlayer who placed the weapon. Check permission, team membership or building authorization on this player. Can be null in theory if the mount is done without a player context, so guard before use.
weaponRackWeaponRackThe WeaponRack entity that received the weapon. Use it to read the rack's owner (OwnerID), position, building privilege and its other stored weapons via the entity's loot container.

Return value

The return value is ignored. The game method continues to return true regardless of what the hook returns, so you cannot cancel or alter a completed mount by returning a value.

How it works

The hook fires inside WeaponRack.MountWeapon, after the item has been moved into the rack's inventory and, if an update was requested, after SendNetworkUpdateImmediate has been sent. Because the call sits just before return true, the weapon is already in the rack when your plugin sees it โ€” you cannot use this hook to veto the mount. Note that the rack tries to call this even when the earlier code path already decided to return early in its own way, but the hook itself only sees successful mounts; there is no callback for a failed attempt.

item is the weapon that went in; it is useful for inventory bookkeeping, logging, per-weapon rewards or attaching metadata by uid. player identifies the actor performing the mount, which is what you check when the feature is permission- or team-gated. weaponRack gives you the entity, so you can read OwnerID, position, and the rack's container contents.

Declaring player as BasePlayer is the natural type and is what the signature passes. There is no narrowing benefit here since the argument is already a BasePlayer; a null value only means no player context, so null-check first. Perform any persistence (data files) quickly โ€” racks can be filled in bursts during raiding or base setup.

Example plugin: Grant a permission and log weapon rack mounts

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

namespace Oxide.Plugins
{
    [Info("Rack Mount Notifier", "RustPluginGenerator", "1.0.0")]
    [Description("Notifies players and admins about weapons stored in weapon racks")]
    public class RackMountNotifier : RustPlugin
    {
        private const string PermAdmin = "rackmountnotifier.admin";
        private const string PermUse = "rackmountnotifier.use";

        private PluginConfig config;
        private readonly Dictionary<string, int> mountCounts = new Dictionary<string, int>();

        private class PluginConfig
        {
            [JsonProperty("Notify player on mount")]
            public bool NotifyPlayer = true;

            [JsonProperty("Notify admins on mount")]
            public bool NotifyAdmins = true;

            [JsonProperty("Warn when player lacks use permission")]
            public bool WarnOnMissingPermission = 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>
            {
                ["Mounted"] = "You stored {0} x{1} in a weapon rack.",
                ["AdminLog"] = "{0} ({1}) stored {2} on rack owned by {3} at {4}",
                ["NoPermission"] = "You do not have permission to use weapon racks here."
            }, 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(PermAdmin, this);
            permission.RegisterPermission(PermUse, this);
        }

        private void OnRackedWeaponMounted(Item item, BasePlayer player, WeaponRack weaponRack)
        {
            if (item?.info == null || weaponRack == null) return;

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

                mountCounts[player.UserIDString] = mountCounts.TryGetValue(player.UserIDString, out var c) ? c + 1 : 1;

                if (config.NotifyPlayer)
                {
                    player.ChatMessage(Msg("Mounted", player.UserIDString, item.info.displayName.english, item.amount));
                }
            }

            if (!config.NotifyAdmins) return;

            var position = weaponRack.transform.position;
            foreach (var admin in BasePlayer.activePlayerList)
            {
                if (admin == null || !permission.UserHasPermission(admin.UserIDString, PermAdmin)) continue;

                admin.ChatMessage(Msg("AdminLog", admin.UserIDString,
                    player != null ? player.displayName : "unknown",
                    player != null ? player.UserIDString : "n/a",
                    item.info.displayName.english,
                    weaponRack.OwnerID,
                    $"({Mathf.RoundToInt(position.x)}, {Mathf.RoundToInt(position.z)})"));
            }
        }

        [ChatCommand("rackcount")]
        private void CmdRackCount(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
            {
                player.ChatMessage(Msg("NoPermission", player.UserIDString));
                return;
            }

            var total = mountCounts.TryGetValue(player.UserIDString, out var c) ? c : 0;
            player.ChatMessage($"Rack mounts this session: {total}");
        }

        private void Unload()
        {
            mountCounts.Clear();
        }
    }
}

The plugin watches OnRackedWeaponMounted and, for every mount, checks the player against a configured permission. Player-facing chat is sent through the language file; admins with the rackmountnotifier.admin permission get a compact broadcast-style chat line showing who stored which weapon on which rack, including the rack owner id so raid logs are searchable. Configuration controls whether the admin line is enabled and whether the player confirmation is sent. The plugin also records a per-player count in memory and exposes a console command to read it, demonstrating a realistic use beyond raw logging, while staying clear of data files and I/O overhead in the hook itself.

Common use cases

  • Raid audit trail

    Log who put which weapon on which rack, with rack OwnerID and position, so admins can reconstruct raid timelines from chat or the console.

  • Permission-gated rack use

    Because the mount completes before the hook, use this hook to detect and warn or penalize players who mount weapons without the required permission; pair it with OnRackedWeaponMount to block up front.

  • Per-rack weapon limits by tier

    Count how many high-tier weapons a rack holds after each mount and alert admins when a rack exceeds a configured threshold, useful on PvE or build-restricted servers.

Pitfalls

  • You cannot veto the mount here

    The hook fires after the item is already inside the rack and after the network update. Return values are ignored, so use OnRackedWeaponMount (which runs before the action) if you need to block it.

  • Player can be null

    Guard against a null player before reading UserIDString or calling permission checks โ€” there are code paths that mount weapons without a live player reference.

  • Keep hook work short

    Racks can be filled rapidly during a raid or base setup. Avoid data file writes and heavy loops inside the hook; queue them with a timer or batch them on save.

Build a plugin with OnRackedWeaponMounted

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

Prompt: Raid audit trail using the OnRackedWeaponMounted 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 OnRackedWeaponMounted

Generate