CanMoveItem
CanMoveItem is called from PlayerInventory.MoveItem before any item relocation is executed, and returning a non-null value cancels the move entirely.
object CanMoveItem(Item item, PlayerInventory playerInventory, ItemContainerId itemContainerId, int targetPosition, int amount, ItemMoveModifier itemMoveModifier)Parameters
| Parameter | Type | Description |
|---|---|---|
item | Item | The Item being moved. Check item.info.shortname to identify what is being moved and item.parent for its current container. |
playerInventory | PlayerInventory | The PlayerInventory the move is performed on. Use playerInventory.player to reach the BasePlayer and its permissions. |
itemContainerId | ItemContainerId | The ItemContainerId of the target container. Match it against playerInventory.containerMain.uid, containerBelt.uid and containerWear.uid to know which destination slot group is used. |
targetPosition | int | The target slot index inside the destination container. -1 usually means the game picks the first free slot. |
amount | int | How many units of the stack are being moved. Compare with item.amount to detect partial splits. |
itemMoveModifier | ItemMoveModifier | The ItemMoveModifier describing the move (for example a quick move or a shift-click). Useful when you only want to block specific kinds of moves. |
Return value
Returning null lets the game continue the move normally. Returning any non-null object (for example true) causes MoveItem to return early, so the item stays where it was and no split, stacking or container change happens.
How it works
The hook fires inside PlayerInventory.MoveItem, right after the game has validated the destination container and before the item is detached, split or inserted. Every inventory move routes through this method: dragging a stack in the inventory UI, shift-click quick transfers between belt, main and wear slots, moving items into a lootable container, and plugin-driven moves that call MoveItem on a player inventory.
The parameters give you the whole context. item is the exact Item instance, playerInventory owns the source and lets you reach playerInventory.player, itemContainerId identifies the destination container by its network id and targetPosition is the destination slot. amount is the quantity being moved, which differs from item.amount on split moves, and itemMoveModifier tells you what kind of move the client requested. Match itemContainerId against playerInventory.containerMain.uid, containerBelt.uid and containerWear.uid to classify the destination.
The signature only has one overload. Returning a value stops the move, so this is a filtering hook: use it for rules like forbidding a shortname in the belt, or restricting quick moves of certain items. There is no way to redirect the move from here; cancel and do the relocation yourself with MoveToContainer if you need that.
Example plugin: Keep restricted items out of the belt
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Belt Item Restriction", "RustPluginGenerator", "1.0.0")]
[Description("Blocks configured items from being moved into a player's belt container")]
public class BeltItemRestriction : RustPlugin
{
private const string PermBypass = "beltitemrestriction.bypass";
private PluginConfig config;
private HashSet<string> blockedShortnames;
private class PluginConfig
{
[JsonProperty("Blocked item shortnames")]
public List<string> BlockedShortnames = new List<string> { "rocket.launcher", "explosive.satchel", "explosive.timed" };
}
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>
{
["Blocked"] = "You cannot place {0} in your belt."
}, 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(PermBypass, this);
blockedShortnames = new HashSet<string>(config.BlockedShortnames, StringComparer.OrdinalIgnoreCase);
}
private object CanMoveItem(Item item, PlayerInventory playerInventory, ItemContainerId itemContainerId, int targetPosition, int amount, ItemMoveModifier itemMoveModifier)
{
if (item?.info == null || playerInventory?.containerBelt == null) return null;
if (!blockedShortnames.Contains(item.info.shortname)) return null;
if (itemContainerId.Value != playerInventory.containerBelt.uid.Value) return null;
BasePlayer player = playerInventory.containerBelt.playerOwner;
if (player == null || player.IsAdmin) return null;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;
player.ChatMessage(Msg("Blocked", player.UserIDString, item.info.displayName.english));
return true;
}
}
}The plugin reads a configurable list of shortnames and blocks moves of those items into the player's belt container. The hook resolves the destination by comparing itemContainerId with playerInventory.containerBelt.uid and checks the shortname against the config set. When a blocked move is detected it returns true to cancel it and sends a localized chat message to the player. Admins and players with the beltitemrestriction.bypass permission are ignored, so staff can still move anything. The default config restricts explosives and rocket launchers, which keeps raiding gear out of the hotbar on PvP servers.
Common use cases
Block raid tools in the hotbar
Prevent rocket launchers, C4 and satchels from being dragged into belt slots while still allowing them in the main inventory.
Custom inventory rules per rank
Give certain permission groups extra allowed shortnames in the wear or belt containers and cancel moves that exceed their allowance.
Stop quick-move from loot containers
Inspect
itemMoveModifierto cancel only fast transfers, forcing players to drag items manually from crates or corpses.
Pitfalls
Comparing containers by reference
The destination arrives as an ItemContainerId, not an ItemContainer. Compare it against the
uidof the player's containers, not against the container objects themselves.Cancelling without feedback
A cancelled move looks like a UI glitch to the player. Send a short chat or console message so they know the action was blocked on purpose.
Hook fires on every move
This is a hot path for inventory-heavy actions. Keep the logic to a set lookup and avoid allocations, logging or physics queries inside the hook.
Plugin recipes that use CanMoveItem
Build a plugin with CanMoveItem
Describe what should happen and get a compiled plugin that uses this hook.
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 CanMoveItem
Generate