OnItemUnwrap
OnItemUnwrap is called when a player triggers the unwrap command on an item that carries an ItemModUnwrap component, before the item is consumed and its contents are rolled.
object OnItemUnwrap(Item item, BasePlayer player, ItemModUnwrap itemModUnwrap)Parameters
| Parameter | Type | Description |
|---|---|---|
item | Item | The wrapped item being unwrapped (for example a present or a mystery box stack). Its amount is already known to be above zero when the hook runs. |
player | BasePlayer | The BasePlayer who issued the unwrap command. May be null in edge cases, so null-check before calling player methods. |
itemModUnwrap | ItemModUnwrap | The ItemModUnwrap component that is handling the command. Use it to read mod data such as reward configuration and ownership phrase settings. |
Return value
Returning null lets the game continue: item.UseItem() runs and rewards are rolled. Returning any non-null value (for example true or an empty string) stops the original code path, so the item is not consumed and no rewards are given.
How it works
The hook fires inside ItemModUnwrap.ServerCommand when the command is unwrap, the item amount is above zero, and the hook returns null. This is the point where presents, boxes and similar wrapped items are about to be consumed and their rewards rolled. item is the stack being opened, player is the requester, and itemModUnwrap gives you the mod's reward configuration. Return a non-null value to stop the original unwrap entirely. Because the third parameter is typed ItemModUnwrap, declare it that way if you need to read mod fields; declaring a broader type such as BaseEntity still matches but loses direct access. This hook only covers the unwrap command path, not other item uses. Keep the body cheap: it can fire repeatedly on large stacks. Use it to gate unwrapping by permission, cooldown or condition rather than to duplicate the reward logic the game already runs.
Example plugin: Require a permission to open wrapped items
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Unwrap Permission Gate", "RustPluginGenerator", "1.0.0")]
[Description("Requires a permission to unwrap items that carry an unwrap mod")]
public class UnwrapPermissionGate : RustPlugin
{
private const string PermUse = "unwrappermissiongate.use";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastDenied = new Dictionary<ulong, float>();
private Timer cleanupTimer;
private class PluginConfig
{
[JsonProperty("Require permission")]
public bool RequirePermission { get; set; } = true;
[JsonProperty("Denied message cooldown seconds")]
public float MessageCooldown { get; set; } = 5f;
[JsonProperty("Exempt item shortnames")]
public List<string> ExemptShortnames { get; set; } = new List<string> { "present" };
}
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>
{
["NoPermission"] = "You do not have permission to unwrap this item.",
}, 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(PermUse, this);
cleanupTimer = timer.Every(60f, CleanupDenied);
}
private void CleanupDenied()
{
float now = Time.realtimeSinceStartup;
foreach (var kvp in new List<KeyValuePair<ulong, float>>(lastDenied))
{
if (now - kvp.Value > 300f) lastDenied.Remove(kvp.Key);
}
}
private object OnItemUnwrap(Item item, BasePlayer player, ItemModUnwrap itemModUnwrap)
{
if (player == null || item == null || item.info == null) return null;
if (!config.RequirePermission) return null;
if (config.ExemptShortnames != null && config.ExemptShortnames.Contains(item.info.shortname)) return null;
if (permission.UserHasPermission(player.UserIDString, PermUse)) return null;
float now = Time.realtimeSinceStartup;
float last;
if (!lastDenied.TryGetValue(player.userID, out last) || now - last > config.MessageCooldown)
{
lastDenied[player.userID] = now;
player.ChatMessage(Msg("NoPermission", player.UserIDString));
}
return true;
}
private void Unload()
{
if (cleanupTimer != null) cleanupTimer.Destroy();
lastDenied.Clear();
}
}
}The plugin registers a single permission and blocks unwrapping for players who lack it. In OnItemUnwrap it null-checks player, then checks permission.UserHasPermission. If the check fails it sends a localized message, avoids hot-path logging, and returns true, which stops the game from consuming the item. A configurable exempt shortname list lets admins whitelist specific wraps. A short cooldown map prevents message spam when a player clicks repeatedly, and is cleaned by a timer that is destroyed in Unload.
Common use cases
Permission-gated unwrapping
Only VIPs or event winners can open certain wrapped items. Returning non-null for unauthorized players keeps the item intact.
Event-only opening windows
Allow unwrapping only during scheduled events by returning non-null outside the window, so players keep their items until the event starts.
Anti-abuse throttling
Reject rapid repeated unwrap attempts to reduce spam or exploit attempts, letting legitimate players through once a cooldown expires.
Pitfalls
Returning false blocks too
Any non-null return stops the unwrap, including
false. Return null when you want to allow it.Only the unwrap command is covered
Other ways an item might be consumed or transformed are not routed through this hook, so do not assume it guards every path.
player can be null
Some command invocations may not carry a player. Null-check before reading permission or sending messages.
Build a plugin with OnItemUnwrap
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 OnItemUnwrap
Generate