Skip to content
RustPluginGenerator

OnCrateHackEnd

OnCrateHackEnd is called when a HackableLockedCrate finishes its hacking countdown and is about to open and drop loot.

Signature
void OnCrateHackEnd(HackableLockedCrate hackableLockedCrate)

Parameters

Hook parameters
ParameterTypeDescription
hackableLockedCrateHackableLockedCrateThe locked crate that just finished its hack timer. Check IsDestroyed before touching it and use net.ID.Value when you need to identify it later.

Return value

The hook is injected with continue behavior into a void method, so whatever you return is ignored and the crate always proceeds to its normal finish logic (analytics, clan score, loot drop). Return nothing.

How it works

The hook fires inside HackableLockedCrate.HackProgress once the accumulated hack time passes requiredHackSeconds. That method is driven by the crate's own update loop while a player is interacting with the laptop in front of it, so the call happens at the exact moment the crate is considered hacked, before the crate rewards the original hacker (clan score and analytics fire right after the hook).

This is the end-of-hack signal, not a progress signal: use OnCrateHack for per-tick progress if you need that. Because the parameter is the crate entity itself, you can read net.ID.Value, its position, OwnerID or loot state at the moment of completion. Declaring the parameter as HackableLockedCrate is already the specific type; there is no narrower type to use, and declaring BaseEntity would still match since the crate derives from it.

The hook fires on the server only. There is no cancel path here, so treat it as a notification for scoring, broadcast, logging or spawning extra loot rather than as a way to stop the crate from opening.

Example plugin: Announce and reward the player who finished a locked crate hack

CrateHackEndNotifier.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Crate Hack End Notifier", "RustPluginGenerator", "1.0.0")]
    [Description("Broadcasts and rewards players when a locked crate is fully hacked.")]
    public class CrateHackEndNotifier : RustPlugin
    {
        private const string PermReward = "cratehackendnotifier.reward";

        private PluginConfig config;

        public class PluginConfig
        {
            [JsonProperty("Broadcast on hack end")]
            public bool Broadcast = true;

            [JsonProperty("Reward item shortname")]
            public string RewardShortname = "scrap";

            [JsonProperty("Reward amount")]
            public int RewardAmount = 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>
            {
                ["Hacked"] = "Locked crate at {0} has been hacked and loot is dropping.",
                ["Reward"] = "You received {0} x {1} for hacking the locked crate."
            }, 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(PermReward, this);
        }

        private void OnCrateHackEnd(HackableLockedCrate hackableLockedCrate)
        {
            if (hackableLockedCrate == null || hackableLockedCrate.IsDestroyed) return;

            string grid = PositionToGrid(hackableLockedCrate.transform.position);

            if (config.Broadcast)
                Server.Broadcast(Msg("Hacked", null, grid));

            BasePlayer hacker = BasePlayer.FindByID(hackableLockedCrate.OwnerID);
            if (hacker == null || !hacker.IsConnected) return;
            if (!permission.UserHasPermission(hacker.UserIDString, PermReward)) return;

            Item item = ItemManager.CreateByName(config.RewardShortname, config.RewardAmount);
            if (item == null) return;

            if (!hacker.inventory.GiveItem(item))
            {
                item.Remove();
                return;
            }

            hacker.ChatMessage(Msg("Reward", hacker.UserIDString, item.amount, item.info.displayName.english));
        }

        private string PositionToGrid(Vector3 position)
        {
            const float cellSize = 146.3f;
            int x = Mathf.FloorToInt((position.x + 2048f) / cellSize);
            int z = Mathf.FloorToInt((position.z + 2048f) / cellSize);
            char letter = (char)('A' + Mathf.Clamp(x, 0, 25));
            return letter + (Mathf.Clamp(z, 0, 99) + 1).ToString();
        }
    }
}

The plugin listens for OnCrateHackEnd, reads the crate's owner id to resolve the hacker, and broadcasts a server-wide message with the crate's map grid position. Players who hold the cratehackendnotifier.reward permission receive a configurable item into their inventory via GiveItem. Messages are stored in the language file so admins can translate them, and all amounts and item shortnames come from the config with null-safe parsing. The hook only runs once per crate, so no timers or cleanup are needed beyond the standard Unload.

Common use cases

  • Reward the hacker

    Give the player who finished the hack a bonus item or a currency call through an optional Economics reference. Combine with OnCrateHack if you need progress-based rewards as well.

  • Broadcast completion to the server

    Send a chat message with the crate grid location so other players know a locked crate has been opened and loot is about to drop.

  • Track hack statistics

    Persist a per-player or per-team count of completed crate hacks to oxide/data for leaderboards or admin reporting.

Pitfalls

  • Not the start of the hack

    Do not use this hook to detect when a player begins hacking; it only fires once hackSeconds exceeds requiredHackSeconds. Use OnCrateHack for progress and OnCrateSpawned for spawn events.

  • Crate may already be destroyed

    If another plugin killed the crate on the same frame, hackableLockedCrate can reference a destroyed entity. Check IsDestroyed before reading position or inventory.

  • Return value is ignored

    Returning false or any other value from this hook does not stop the crate from opening. Guard logic inside the hook body instead.

Build a plugin with OnCrateHackEnd

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Reward the hacker using the OnCrateHackEnd 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 OnCrateHackEnd

Generate