Skip to content
RustPluginGenerator

OnLootSpawn

OnLootSpawn is called right before a loot container's inventory is populated with generated loot, or before a delayed LootFill writes its items. Returning a non-null value skips the fill.

Signature
object OnLootSpawn(LootContainer lootContainer)

Parameters

Hook parameters
ParameterTypeDescription
lootContainerLootContainerThe LootContainer whose inventory is about to be filled, or the LootFill object when the hook fires from a delayed fill. Cast or type-check before using it.

Return value

Returning null lets the vanilla fill run. Returning any non-null value makes the game skip PopulateLoot() / CancelLootRefreshCountdown() in SpawnLoot, and skip FillLoot in DelayFill, leaving the container empty unless you filled it.

How it works

Oxide fires this hook inside LootContainer.SpawnLoot, after the container's inventory has been cleared, and again inside LootFill.DelayFill for containers that use a deferred fill. In SpawnLoot a non-null return skips PopulateLoot() and the refresh countdown cancellation, so the container stays empty until something repopulates it. In DelayFill a non-null return skips LootContainer.FillLoot, leaving the storage container empty.

The parameter is the LootContainer for the first injection and a LootFill for the second. Since the parameter type in your hook method must line up with the argument at each injection site, you should declare object and check as LootContainer / as LootFill if you need to inspect it. Return null to let the game fill the container as normal.

Practical uses: selective loot tables, blocking loot in specific areas, or pre-seeding items yourself. If you fill the container yourself, still return a non-null value so the game does not overwrite your items.

Other signatures

Oxide also calls OnLootSpawn from other places in the game with these parameter types. Declare the overload you need, or several:

  • object OnLootSpawn(LootFill lootFill)

Example plugin: Replace crate loot with a configurable item list

CustomLootSpawn.cs
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("CustomLootSpawn", "RustPluginGenerator", "1.0.0")]
    [Description("Replaces loot in matching containers with a configurable item list.")]
    public class CustomLootSpawn : RustPlugin
    {
        private const string PermBypass = "customlootspawn.bypass";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Prefab shortnames (leave a match to override loot)")]
            public List<string> Prefabs = new List<string> { "crate_normal", "crate_basic" };

            [JsonProperty("Items to give (shortname amount)")]
            public List<string> Items = new List<string> { "rifle.ak 1", "ammo.rifle 90", "bandage 5" };

            [JsonProperty("Log each override to console")]
            public bool LogOverrides = 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);

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

        private object OnLootSpawn(object source)
        {
            if (source == null) return null;

            var container = source as LootContainer;
            if (container == null) return null;
            if (container.inventory == null) return null;
            if (string.IsNullOrEmpty(container.ShortPrefabName)) return null;
            if (!config.Prefabs.Contains(container.ShortPrefabName)) return null;

            FillContainer(container);

            if (config.LogOverrides)
                Puts($"Seeded {container.ShortPrefabName} at {container.transform.position}");

            return true;
        }

        private void FillContainer(LootContainer container)
        {
            var inv = container.inventory;
            inv.Clear();

            foreach (var line in config.Items)
            {
                if (string.IsNullOrEmpty(line)) continue;
                var parts = line.Split(' ');
                if (parts.Length < 1) continue;

                string shortname = parts[0];
                int amount = 1;
                if (parts.Length >= 2) int.TryParse(parts[1], out amount);
                if (amount <= 0) continue;

                var item = ItemManager.CreateByName(shortname, amount, 0UL);
                if (item == null)
                {
                    PrintWarning($"Unknown item shortname in config: {shortname}");
                    continue;
                }

                if (!item.MoveToContainer(inv))
                {
                    item.Remove();
                }
            }

            inv.MarkDirty();
        }
    }
}

The plugin reads a config with a list of shortname amount entries. When OnLootSpawn fires, it matches the container's short prefab name against a configurable whitelist. If matched, it clears nothing extra (the game already cleared it), gives the configured items into lootContainer.inventory, marks the container dirty, and returns true so the vanilla fill is skipped. Containers not on the list return null and fill normally. CanLootEntity is overridden to prevent non-admins from pulling mixed loot when the container was pre-populated by us — actually we keep it simple and skip that. Only OnLootSpawn is used.

Common use cases

  • Reserved loot for admins

    Detect containers spawned in priority areas and fill them with a curated loadout for whitelisted player IDs.

  • Event crates

    When the server operator starts a custom event, mark crates so OnLootSpawn seeds them with weapons and resources.

  • Empty containers in a zone

    Return true for containers inside a no-loot zone before the game fills them, then notify the player via CanLootEntity or a chat hint.

Pitfalls

  • Two signatures, one object parameter

    The hook fires with a LootContainer from SpawnLoot and a LootFill from DelayFill. Declare the parameter as object and check the type, or you will miss the delayed fills.

  • Returning true without filling leaves it empty

    Blocks the vanilla fill but does not add anything. If that is not the goal, populate lootContainer.inventory yourself and call MarkDirty() before returning.

  • Hook fires often on busy servers

    Do not call Puts/PrintWarning unconditionally here. Cache config lookups outside the hook.

Plugin recipes that use OnLootSpawn

Build a plugin with OnLootSpawn

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

Prompt: Reserved loot for admins using the OnLootSpawn 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 OnLootSpawn

Generate