CanStackItem
CanStackItem is called from Item.CanStack when the server checks whether two items of the same type can be merged into one stack. Returning a bool forces the answer; returning null lets the default comparison run.
object CanStackItem(Item item, Item item2)Parameters
| Parameter | Type | Description |
|---|---|---|
item | Item | The Item instance the game is trying to stack into. This is the item `CanStack` was called on, i.e. the destination stack. |
item2 | Item | The other item being tested against the destination. The game compares this one to `item` for prefab, skin, and stack limits. |
Return value
Return true to allow stacking, false to forbid it, or null/any non-bool value to let the vanilla logic decide. The game returns your bool directly as the result of Item.CanStack.
How it works
The hook fires inside Item.CanStack(Item), which the server calls whenever it evaluates whether two item instances may be combined. Typical triggers are picking up an item that matches one in your inventory, moving a stack onto another in a container, splitting a stack and merging it back, and any internal inventory operation that tries to consolidate stacks.
Both parameters are Item objects: item is the destination (the instance whose method ran) and item2 is the candidate being tested. Useful members are info.shortname, skin, amount, info.stackable, and parent — compare these when you want to allow or forbid a merge.
You cannot narrow this hook by declaring a more specific parameter type: both parameters are always Item, and Oxide's dispatch still matches them. There is only one signature.
Because the hook runs on every stack check, keep the body cheap and avoid logging. A common use is blocking merges of items with different skins or custom data so a player's modified item does not disappear into a plain stack.
Example plugin: Block merging items that carry different skins
using System;
using Newtonsoft.Json;
namespace Oxide.Plugins
{
[Info("Skin Safe Stacking", "RustPluginGenerator", "1.0.0")]
[Description("Prevents items with different skins from merging into one stack.")]
public class SkinSafeStacking : RustPlugin
{
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Block merges of items with different skins")]
public bool BlockDifferentSkins { get; set; } = 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);
private object CanStackItem(Item item, Item item2)
{
if (item?.info == null || item2?.info == null) return null;
if (!config.BlockDifferentSkins) return null;
if (item.info.itemid != item2.info.itemid) return null;
if (item.skin != item2.skin) return false;
return null;
}
}
}The plugin overrides CanStackItem and refuses a merge when the two items have different skins, so a skinned or custom-skinned item is never absorbed into a plain vanilla stack. It also reads a config flag that lets admins turn the protection off entirely, in which case the hook returns null and vanilla behavior resumes. Every parameter is null-checked, and the hook body only compares two integer values, so it stays cheap on a busy server. The class registers no commands or permissions because the behavior is purely passive.
Common use cases
Protect skinned items
Refuse merges when
skindiffers so a painted weapon or clothing item does not vanish into a default-skin stack.Prevent cross-container merges
Return
falsewhen the two items have differentparentcontainers, keeping stacks where the player left them.Cap merges for custom items
Allow a merge only while the combined
amountstays under a limit you define, then let the game handle the remainder normally.
Pitfalls
Fires very often
The hook runs on every stack evaluation, including automatic inventory consolidation. Never call
PutsorPrintWarninginside it and keep comparisons simple.Returning a value skips vanilla checks
A returned
truebypasses the game's own prefab, skin, and stackable checks, so you can create oversized or mismatched stacks. Only returntruewhen you fully understand the items involved.Skin 0 is the default
Items created without an explicit skin have
skin == 0. Comparing skins directly handles that, but do not treat 0 as "invalid" or you will block ordinary stacking.
Build a plugin with CanStackItem
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 CanStackItem
Generate