Skip to content
RustPluginGenerator

CanMannequinSwap

CanMannequinSwap is called when a player requests to swap the clothing/equipment on a Mannequin, before the game checks its lock and opens the mannequin's loot. Returning a non-null value cancels the swap.

Signature
object CanMannequinSwap(Mannequin mannequin, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
mannequinMannequinThe Mannequin entity the player is trying to change the outfit on. Use it to read the owner (OwnerID), position, inventory or flags.
playerBasePlayerThe BasePlayer who sent the swap request. Check permissions, team membership or distance against the mannequin here.

Return value

Return null to let the request proceed to the mannequin's lock check and normal swap logic. Return any non-null value (for example false or a string) to stop the request immediately; the original method returns without swapping or opening loot, and the return value itself is not used for anything else.

How it works

The hook fires inside Mannequin.Server_RequestSwap, which runs server side when a player sends a swap request for a mannequin they are interacting with. It runs after the equipping guard and after the game's own CanBeLooted(player) and IsDead() checks, but before the mannequin's lock is validated and before the loot UI would open. Returning anything non-null aborts the request, so the player stays where they are with no swap.

Use player to evaluate permissions, team membership, distance to the mannequin, or combat state, and mannequin to read OwnerID, transform.position, or installed items. Because the parameters are already exact game types there is no practical narrowing to do; both arguments are always provided. Restrict frequent work here since a swap request is cheap to spam, and avoid printing inside the hook. The canceled action leaves the lock check untouched, so this is a good place for custom ownership rules on mannequins.

Example plugin: Lock mannequin swaps to the owner or their team

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

namespace Oxide.Plugins
{
    [Info("Mannequin Owner Lock", "RustPluginGenerator", "1.0.0")]
    [Description("Restricts mannequin outfit swaps to the owner or their team members.")]
    public class MannequinOwnerLock : RustPlugin
    {
        private const string PermAdmin = "mannequinownerlock.admin";
        private const string PermBypass = "mannequinownerlock.bypass";

        private PluginConfig config;
        private readonly Dictionary<ulong, float> lastWarning = new Dictionary<ulong, float>();

        private class PluginConfig
        {
            [JsonProperty("Only owner and teammates can swap")]
            public bool OwnerAndTeamOnly { get; set; } = true;

            [JsonProperty("Chat warning cooldown in seconds")]
            public float WarningCooldown { get; set; } = 5f;
        }

        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>
            {
                ["NotAllowed"] = "This mannequin belongs to {0}. Only the owner or their team can change it.",
                ["Denied"] = "You are not allowed to change this mannequin."
            }, 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(PermBypass, this);
        }

        private object CanMannequinSwap(Mannequin mannequin, BasePlayer player)
        {
            if (mannequin == null || player == null || !config.OwnerAndTeamOnly)
                return null;

            if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, PermBypass))
                return null;

            ulong ownerId = mannequin.OwnerID;
            if (ownerId == 0UL || ownerId == player.userID)
                return null;

            if (SharesTeam(player, ownerId))
                return null;

            Warn(player, ownerId);
            return false;
        }

        private bool SharesTeam(BasePlayer player, ulong ownerId)
        {
            if (player.currentTeam == 0UL)
                return false;

            RelationshipManager.PlayerTeam team = RelationshipManager.ServerInstance.FindTeam(player.currentTeam);
            if (team == null)
                return false;

            return team.members.Contains(ownerId);
        }

        private void Warn(BasePlayer player, ulong ownerId)
        {
            float now = UnityEngine.Time.realtimeSinceStartup;
            float next;
            if (lastWarning.TryGetValue(player.userID, out next) && now < next)
                return;

            lastWarning[player.userID] = now + Mathf.Max(1f, config.WarningCooldown);

            BasePlayer owner = BasePlayer.FindByID(ownerId);
            string ownerName = owner != null ? owner.displayName : "another player";
            player.ChatMessage(Msg("NotAllowed", player.UserIDString, ownerName));
        }

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

The plugin blocks swaps on mannequins by anyone who is not the mannequin's owner or a teammate of the owner. CanMannequinSwap compares mannequin.OwnerID with player.userID; on a mismatch it resolves both players' teams through RelationshipManager.ServerInstance.FindTeam and only allows the swap when both share a non-zero team ID. Admins are exempt, and a config flag lets a server turn the whole check off. Denied players get a localized chat message with the mannequin owner's name and a throttled warning variable keeps chat spam down. Returning false cancels the request before the lock and loot logic run, so nothing is swapped and no UI opens.

Common use cases

  • Owner and team restrictions

    Allow only the mannequin owner or their teammates to re-dress it, keeping public display mannequins protected on roleplay servers.

  • Raid protection during combat

    Cancel swaps while the requesting player has recently taken damage or is building blocked, so raiders cannot strip gear from mannequins mid-fight.

  • Distance and permission gating

    Require a permission node and a minimum distance check against the mannequin position to stop remote or scripted swap attempts.

Pitfalls

  • Not the loot gate

    This hook covers swap requests only; the mannequin's storage container is opened through the loot path, so blocking here does not stop all interaction with the mannequin.

  • Returning false vs true

    The method is void and the result is only checked for non-null, so both true and false cancel the request. Returning a boolean can mislead readers into thinking one value allows the swap; use null for allow.

  • OwnerID of zero

    Mannequins placed by the server or map can have an OwnerID of 0. Your ownership logic has to decide whether that means public access or a hard block, otherwise those mannequins become freely editable.

Build a plugin with CanMannequinSwap

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

Prompt: Owner and team restrictions using the CanMannequinSwap 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 CanMannequinSwap

Generate