Skip to content
RustPluginGenerator

OnCrateLaptopAttack

OnCrateLaptopAttack is called when a player hits the laptop part of a HackableLockedCrate during its hacking phase, before the shock effect plays and before hack time is reduced.

Signature
object OnCrateLaptopAttack(HackableLockedCrate hackableLockedCrate, HitInfo info)

Parameters

Hook parameters
ParameterTypeDescription
hackableLockedCrateHackableLockedCrateThe HackableLockedCrate entity being hacked. Use it to read position, net.ID, OwnerID, secondsRemaining or to call Hurt/Kill.
infoHitInfoThe HitInfo for the hit that landed on the laptop collision bone. Contains InitiatorPlayer, damageTypes (total and per-type), HitPositionWorld and the weapon used.

Return value

Returning a non-null value (for example true) stops the original code path: the shock effect is not played and hack seconds are not reduced. Returning null lets the game continue normally, applying the shock effect and subtracting hack time based on the hit damage.

How it works

The hook fires inside HackableLockedCrate.OnAttacked on the server, and only when the hit bone resolves to laptopcollision. That means the player must physically strike the laptop panel on the crate, not just damage the crate body: a hit on any other bone never reaches this hook. hackableLockedCrate is the crate itself and info carries the attacker (InitiatorPlayer), the damage types and the world hit position.

Because it fires per hit, this is the place to inspect who is tampering with an active hack and with what. You can read info.damageTypes.Total() to know how much hack progress the hit would remove (the game scales hack seconds by total damage divided by 50 and multiplies by 8), or check info.WeaponPrefab to see whether a tool, melee weapon or projectile was used.

Declaring info as HitInfo is the only supported shape; there is no narrower variant because the crate type is already fixed. Keep the handler cheap: it can fire many times per second while someone is attacking.

Example plugin: Notify owners when their airdrop crate laptop is hit

CrateLaptopAlert.cs
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Rust;

namespace Oxide.Plugins
{
    [Info("CrateLaptopAlert", "RustPluginGenerator", "1.0.0")]
    [Description("Reports and optionally blocks laptop hits on hacked crates from players outside the owner's team")]
    public class CrateLaptopAlert : RustPlugin
    {
        private const string PermAdmin = "cratelaptopalert.admin";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Block unauthorized laptop hits")]
            public bool BlockHits = true;

            [JsonProperty("Alert the crate owner")]
            public bool AlertOwner = true;

            [JsonProperty("Notify admins online")]
            public bool NotifyAdmins = false;
        }

        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>
            {
                ["CrateAttacked"] = "Someone is hitting your hacked crate at {0}.",
                ["AttackerBlocked"] = "You cannot damage another player's hacked crate.",
                ["AdminAlert"] = "{0} attacked a hacked crate owned by {1}."
            }, this);
        }

        private void Init()
        {
            permission.RegisterPermission(PermAdmin, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
        {
            return string.Format(lang.GetMessage(key, this, userId), args);
        }

        private object OnCrateLaptopAttack(HackableLockedCrate hackableLockedCrate, HitInfo info)
        {
            if (hackableLockedCrate == null || info == null) return null;

            BasePlayer attacker = info.InitiatorPlayer;
            if (attacker == null || attacker.IsNpc) return null;

            ulong ownerId = hackableLockedCrate.OwnerID;
            if (ownerId == 0 || attacker.userID.Get() == ownerId) return null;

            if (SameTeam(ownerId, attacker.userID.Get())) return null;

            if (config.AlertOwner)
            {
                BasePlayer owner = BasePlayer.FindByID(ownerId);
                if (owner != null && owner.IsConnected)
                {
                    owner.ChatMessage(Msg("CrateAttacked", owner.UserIDString, PositionText(hackableLockedCrate.transform.position)));
                }
            }

            if (config.NotifyAdmins)
            {
                string ownerName = covalence.Players.FindPlayerById(ownerId.ToString())?.Name ?? ownerId.ToString();
                string message = Msg("AdminAlert", null, attacker.displayName, ownerName);
                foreach (BasePlayer player in BasePlayer.activePlayerList)
                {
                    if (player != null && permission.UserHasPermission(player.UserIDString, PermAdmin))
                    {
                        player.ChatMessage(message);
                    }
                }
            }

            if (!config.BlockHits) return null;

            attacker.ChatMessage(Msg("AttackerBlocked", attacker.UserIDString));
            return true;
        }

        private bool SameTeam(ulong firstId, ulong secondId)
        {
            BasePlayer first = BasePlayer.FindByID(firstId);
            if (first == null || first.currentTeam == 0) return false;
            return first.currentTeam == BasePlayer.FindByID(secondId)?.currentTeam && first.currentTeam != 0;
        }

        private static string PositionText(UnityEngine.Vector3 position)
        {
            return $"({(int)position.x}, {(int)position.z})";
        }
    }
}

The plugin watches every hit on an actively hacked crate's laptop panel. When the attacker is not the crate owner and the attacker is not on the same team as the owner, it cancels the hit by returning true so no hack progress is lost, then sends a chat message to the owner if they are online. Messages come from the language file so admins can translate them. Team checks use RelationshipManager.ServerInstance.FindTeam, guarded against a missing team. Optional config toggles blocking and alerting independently, which lets server owners use it purely as a monitor on PvE-style setups.

Common use cases

  • Protect crates during a hack

    Cancel hits that come from players outside the owner's team, so a passing player cannot stall or reverse an in-progress hack on an airdrop crate.

  • Log attack attempts

    Record who hit the laptop, with what weapon and how much damage, into a data file for offline review of contested crates.

  • Scale hack time

    Let hits through but notify nearby players that the crate is under attack, or adjust rules by examining the attacker's damage type before deciding to return null.

Pitfalls

  • Only laptop hits reach the hook

    Hits on other bones of the crate bypass OnCrateLaptopAttack entirely. Use OnEntityTakeDamage if you need to observe all damage to the crate.

  • Fires very often

    A player repeatedly striking the laptop triggers this hook many times per second. Avoid Puts, PrintWarning and data writes inside the handler.

  • Team check needs a null guard

    FindTeam returns null when the crate owner is not in a team and currentTeam is 0. Guard the lookup before reading members.

Build a plugin with OnCrateLaptopAttack

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

Prompt: Protect crates during a hack using the OnCrateLaptopAttack 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 OnCrateLaptopAttack

Generate