CanSeeStash
CanSeeStash is called when a player has stared at a hidden stash long enough to reveal it, right before the stash is unhidden. Returning a non-null value cancels the reveal for that detection tick.
object CanSeeStash(BasePlayer player, StashContainer stash)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer whose proximity and look detection is about to reveal the buried stash. Use it to identify the viewer or to apply per-player permission checks. |
stash | StashContainer | The StashContainer (named Entity in the signature) that is about to be uncovered. Check its OwnerID, position or identity to decide whether this particular stash should reveal. |
Return value
Returning a non-null value stops the original code path, so the stash stays hidden and no OnStashRevealed analytics or unhide happens. Returning null (or matching nothing) lets the game continue and call SetHidden(false) to reveal the stash to that player.
How it works
The hook fires inside BasePlayer.CheckStashRevealInvoke, which the game runs while a player is looking at a nearby hidden stash. The reveal only reaches this point once the stash IsHidden() is true, the player is within range (PlayerInRange), and the accumulated LookingAtTime has reached the stash's uncoverTime. At that moment Rust asks Oxide's CanSeeStash whether the reveal may proceed.
Use player to check group, permission or team against the stash owner, and stash to inspect OwnerID, net.ID.Value, position or any stored state. Because the game only calls the hook at the instant a reveal would happen, the accumulated look timer keeps growing between calls, so after the reveal is cancelled it will attempt again on the next detection tick until you allow it or the player looks away.
The parameters are already specific types (BasePlayer, StashContainer), so declaring them as-is is the normal pattern; declaring a broader base type would not narrow anything meaningfully. Keep the method cheap because it can be invoked repeatedly while a player stares at a stash.
Example plugin: Only reveal stashes to their owner or the owner's team
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Stash Owner Reveal", "RustPluginGenerator", "1.0.0")]
[Description("Controls which players can reveal a hidden stash by looking at it.")]
public class StashOwnerReveal : RustPlugin
{
private const string PermBypass = "stashownerreveal.bypass";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastDeniedAt = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Allow team members to reveal stashes")]
public bool AllowTeam { get; set; } = true;
[JsonProperty("Admins bypass restrictions")]
public bool AdminBypass { get; set; } = true;
[JsonProperty("Denied message cooldown (seconds)")]
public float DeniedCooldown { get; set; } = 10f;
}
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>
{
["NotYourStash"] = "This stash does not belong to you."
}, 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);
}
private void Unload()
{
lastDeniedAt.Clear();
}
private object CanSeeStash(BasePlayer player, StashContainer stash)
{
if (player == null || stash == null) return null;
if (player.IsAdmin && config.AdminBypass) return null;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;
ulong ownerId = stash.OwnerID;
if (ownerId == 0 || ownerId == player.userID.Get()) return null;
if (config.AllowTeam && player.currentTeam != 0)
{
var team = RelationshipManager.ServerInstance.FindTeam(player.currentTeam);
if (team != null && team.members.Contains(ownerId)) return null;
}
NotifyDenied(player, stash);
return true;
}
private void NotifyDenied(BasePlayer player, StashContainer stash)
{
ulong id = stash.net.ID.Value;
float now = Time.realtimeSinceStartup;
float last;
if (lastDeniedAt.TryGetValue(id, out last) && now - last < config.DeniedCooldown) return;
lastDeniedAt[id] = now;
player.ChatMessage(Msg("NotYourStash", player.UserIDString));
}
}
}The plugin blocks every stash reveal unless the viewer is the stash owner, an admin, or on the same team as the owner. The hook returns a non-null value to cancel the reveal and null to allow it. A language message is sent when a reveal is denied so the player gets feedback, and a short cooldown map keyed by the stash network id prevents the same message from spamming every detection tick the player keeps staring. The config exposes an option to allow team-wide reveals and an option to skip admins.
Common use cases
Owner-only stash protection
Stop other players from uncovering a stash simply by staring at it, forcing them to find it another way.
Team-wide stash sharing
Allow reveals only when the viewer is on the same team as the stash owner, so group members can access shared stashes.
Admin and event control
Bypass the restriction for admins, or disable reveals entirely during a special event by returning non-null unconditionally.
Pitfalls
The hook repeats every detection tick
Cancelling the reveal does not reset the look timer, so the hook fires again shortly after. Guard any chat or effect output to avoid spam.
Stash OwnerID can be 0
A stash with no owner (or one placed before ownership was set) will never match a player id; decide explicitly whether such stashes should be revealed.
Return null to allow
Any non-null object blocks the reveal. Returning false still counts as non-null and keeps the stash hidden, so return null when you mean to permit it.
Build a plugin with CanSeeStash
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 CanSeeStash
Generate