Skip to content
RustPluginGenerator

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.

Signature
void OnCrateDropped(HackableLockedCrate hackableLockedCrate)

Parameters

Hook parameters
ParameterTypeDescription
hackableLockedCrateHackableLockedCrateThe 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

CrateDropAnnouncer.cs
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 wasDropped flag 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.

Prompt: Announce crate drops to the server using the OnCrateDropped hook, with a config file and a permission
Generate this plugin

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