OnCrateDropped
OnCrateDropped is called when a HackableLockedCrate (the hackable locked crate from cargo ship / oil rig style events) marks itself as dropped, right after its internal wasDropped flag is set to true.
void OnCrateDropped(HackableLockedCrate hackableLockedCrate)Parameters
| Parameter | Type | Description |
|---|---|---|
hackableLockedCrate | HackableLockedCrate | The HackableLockedCrate entity whose wasDropped flag is being set. It is a live BaseEntity subclass, so you can read net.ID, transform.position, OwnerID and its hack timer state from it. |
Return value
The return value is ignored. The game sets wasDropped = true and calls the hook purely for notification, so nothing you return changes the crate's state or prevents the drop.
How it works
The hook fires inside HackableLockedCrate.SetWasDropped, immediately after the crate sets its internal wasDropped flag. That method is the game's way of recording that this hackable locked crate has been released from its carrier and is now free-standing (for example after being dismounted from a cargo ship or otherwise dropped), so the hook signals the transition from carried to dropped state for that one crate instance.
The single parameter is the crate entity itself. Position, net.ID.Value, OwnerID, ShortPrefabName and current loot inventory contents are all readable at this point, which makes the hook a natural place to snapshot crate data, tag the crate for tracking, or notify players about a newly dropped crate.
The injection uses a plain continue behavior, so the return value is ignored and the crate proceeds normally. You cannot cancel the drop or alter the flag from this hook.
Because the crate may already be spawned and networked when this runs, treat it as an event notification rather than an authoring point. It fires once per drop transition per crate, not repeatedly.
Example plugin: Broadcast hackable crate drops with map grid and timer
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Crate Drop Announcer", "RustPluginGenerator", "1.0.0")]
[Description("Announces hackable locked crate drops in chat with their map grid position.")]
public class CrateDropAnnouncer : RustPlugin
{
private const string PermReceive = "cratedropannouncer.receive";
private PluginConfig config;
public class PluginConfig
{
[JsonProperty("Announce to all players")]
public bool AnnounceToAll { get; set; } = true;
[JsonProperty("Announce to players with permission only")]
public bool PermissionOnly { get; set; } = false;
[JsonProperty("Include hack timer remaining")]
public bool IncludeTimer { 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);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["CrateDropped"] = "A hackable locked crate has dropped at grid {0}.",
["CrateDroppedTimer"] = "A hackable locked crate has dropped at grid {0} ({1}s hack timer)."
}, 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(PermReceive, this);
}
private void OnCrateDropped(HackableLockedCrate hackableLockedCrate)
{
if (hackableLockedCrate == null || hackableLockedCrate.IsDestroyed) return;
string grid = GridReference(hackableLockedCrate.transform.position);
string text;
if (config.IncludeTimer)
{
float remaining = hackableLockedCrate.hackSeconds > 0f ? hackableLockedCrate.hackSeconds : 0f;
text = Msg("CrateDroppedTimer", null, grid, Mathf.Max(0f, remaining).ToString("0"));
}
else
{
text = Msg("CrateDropped", null, grid);
}
if (!config.PermissionOnly || config.AnnounceToAll)
{
foreach (var player in BasePlayer.activePlayerList)
{
if (player == null) continue;
if (config.PermissionOnly && !permission.UserHasPermission(player.UserIDString, PermReceive)) continue;
player.ChatMessage(text);
}
}
else
{
foreach (var player in BasePlayer.activePlayerList)
{
if (player == null) continue;
if (!permission.UserHasPermission(player.UserIDString, PermReceive)) continue;
player.ChatMessage(text);
}
}
}
private static string GridReference(Vector3 position)
{
const float cellSize = 146.3f;
int x = Mathf.FloorToInt((position.x + 2048f) / cellSize);
int z = Mathf.FloorToInt((position.z + 2048f) / cellSize);
if (x < 0 || z < 0) return $"{x},{z}";
char letter = (char)('A' + Mathf.Clamp(x, 0, 25));
return $"{letter}{z}";
}
}
}The plugin listens to OnCrateDropped and turns each hackable crate drop into a server-wide chat announcement. It reads the crate's transform.position, converts it to a map grid label using the string formatters built into Vector3 rounding plus a manual grid calculation, then broadcasts a localized message with the grid and the crate's hack countdown remaining. LoadDefaultMessages registers the announcement text so admins can translate it, and LoadConfig exposes a simple enable toggle. Because the hook has no return effect, the plugin never touches the crate itself, keeping behavior predictable and safe for any server that loads it alongside other crate plugins.
Common use cases
Announce crate drops to the server
Send a chat or Discord-relayed message with the crate's map grid so players know a hackable locked crate is now free-standing and worth contesting.
Track hackable crate lifecycles
Record the crate ID and drop timestamp in a data file or external log so admins can audit how often crates drop and whether they are hacked afterwards.
Tag dropped crates for custom loot
Store the crate's net ID in memory, then later inspect it in other hooks or commands to apply custom rewards if and when the crate is successfully hacked.
Pitfalls
It is a notification, not a hook you can block
Returning a value does nothing because the injection ignores the return. Use it to observe or announce, not to prevent or alter the drop.
The crate is already dropped when you see it
The
wasDroppedflag is already true before the hook fires, so do not attempt to infer its previous state from the entity. Keep your own record if you need the before/after distinction.Position may be mid-air
If the crate is dropped from height it may still be falling when the hook fires. Snapping the current position for a map grid is usually fine, but avoid spawning objects exactly at that point until the crate has settled.
Build a plugin with OnCrateDropped
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 OnCrateDropped
Generate