OnStashExposed
OnStashExposed is called after a player reveals a buried StashContainer, once the stash has been switched from hidden to visible.
void OnStashExposed(StashContainer stash, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
stash | StashContainer | The StashContainer that the player just exposed. It has already been unhidden when the hook fires, so you can read its inventory, position and owners. |
player | BasePlayer | The BasePlayer whose reveal check triggered the callback. This is the player standing near and looking at the stash. |
Return value
The return value is ignored; the reveal completes regardless of what your hook method returns. Return type void is the natural choice.
How it works
The hook fires inside BasePlayer.CheckStashRevealInvoke, the periodic check a player runs while looking around. When the player's aim settles on a nearby hidden stash long enough, the game calls SetHidden(false) on it, records the reveal in analytics and then invokes OnStashExposed with the stash and the looking player. It does not fire when a player opens an already visible stash, and it does not fire for other container types.
Use the parameters to react to a specific player finding a specific stash: log who found what, notify a team, apply a cooldown, or mark the stash for later handling. Because the stash is already visible, you can inspect stash.inventory and stash.OwnerID at this point.
The hook is void, so you cannot cancel the reveal by returning a value. If you need to prevent exposure, do it elsewhere (for example by intercepting the reveal check or moving the stash). Declaring a narrower type than StashContainer is not useful here since the argument is always a stash.
Example plugin: Log and announce stash finds
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Stash Reveal Announcer", "RustPluginGenerator", "1.0.0")]
[Description("Logs and optionally announces when players expose hidden stashes")]
public class StashRevealAnnouncer : RustPlugin
{
private const string PermAnnounce = "stashrevealannouncer.announce";
private PluginConfig config;
private readonly List<string> recentReveals = new List<string>();
private class PluginConfig
{
[JsonProperty("Broadcast finds to all players")]
public bool BroadcastFinds { get; set; } = false;
[JsonProperty("Message the finding player")]
public bool MessageFinder { get; set; } = true;
[JsonProperty("Keep recent reveals in data file")]
public int KeepRecent { get; set; } = 50;
}
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>
{
["Reveal"] = "You exposed a stash at {0}.",
["Broadcast"] = "{0} exposed a stash at {1}."
}, 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(PermAnnounce, this);
LoadReveals();
}
private void Unload()
{
SaveReveals();
}
private void OnStashExposed(StashContainer stash, BasePlayer player)
{
if (stash == null || player == null) return;
Vector3 pos = stash.transform.position;
string coords = $"{pos.x:F1}, {pos.z:F1}";
if (config.MessageFinder && player.IsConnected)
player.ChatMessage(Msg("Reveal", player.UserIDString, coords));
if (config.BroadcastFinds)
Server.Broadcast(Msg("Broadcast", null, player.displayName, coords));
recentReveals.Add($"{DateTime.UtcNow:u} {player.displayName} ({player.UserIDString}) at {coords}");
while (recentReveals.Count > Mathf.Max(1, config.KeepRecent))
recentReveals.RemoveAt(0);
SaveReveals();
}
private void LoadReveals()
{
recentReveals.Clear();
var data = Interface.Oxide.DataFileSystem.ReadObject<List<string>>(Name);
if (data != null) recentReveals.AddRange(data);
}
private void SaveReveals()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, recentReveals);
}
}
}The plugin listens for OnStashExposed and records each reveal. It builds a short message with the player name and the stash position, sends it to the player through the language system and optionally broadcasts it to the server when Broadcast Finds is enabled in the config. Reveals are also appended to a rolling in-memory log and written to oxide/data/StashRevealAnnouncer so admins can review recent finds after a restart. Because the hook fires only when a player actually uncovers a stash, the log stays small and the messages are not spammed.
Common use cases
Admin audit trail
Persist who exposed which stash and where, so staff can trace suspicious stash hunting or investigate reports of stashes being found in raid-protected areas.
Team alerts
Notify the stash owner's team that a hidden stash was discovered, using
player.currentTeamandRelationshipManagerto resolve members.Reward exploration
Grant a small reward or achievement the first time a player uncovers a stash on the map, tracked per player in saved data.
Pitfalls
You cannot cancel the reveal
The hook is informational and the original code path continues; returning a value does nothing. Block exposure earlier in the reveal check instead.
Fires for the looking player only
The stash is already visible by the time the hook runs, so other players who walk up afterwards will not produce another call for the same stash.
Stash may be empty or owned
Always null-check
stash.inventorybefore reading items, and treatOwnerID0 as unowned rather than assuming a player.
Build a plugin with OnStashExposed
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 OnStashExposed
Generate