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.
object OnLootSpawn(LootContainer lootContainer)Parameters
| Parameter | Type | Description |
|---|---|---|
lootContainer | LootContainer | The 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
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
OnLootSpawnseeds them with weapons and resources.Empty containers in a zone
Return
truefor containers inside a no-loot zone before the game fills them, then notify the player viaCanLootEntityor a chat hint.
Pitfalls
Two signatures, one object parameter
The hook fires with a
LootContainerfromSpawnLootand aLootFillfromDelayFill. Declare the parameter asobjectand 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.inventoryyourself and callMarkDirty()before returning.Hook fires often on busy servers
Do not call
Puts/PrintWarningunconditionally here. Cache config lookups outside the hook.
Plugin recipes that use OnLootSpawn
- How to make a Rust custom loot table plugin (crates by prefab)Replaces the contents of configured LootContainer crates, matched by short prefab name, with weighted items that have per-item chances and min/max amounts. Uses OnLootSpawn(LootContainer).
- How to make a Rust loot multiplier plugin (Oxide/Carbon)This plugin multiplies the stack sizes of items generated inside loot containers such as crates and barrels, using a global multiplier, per-item overrides and a blacklist. It hooks OnLootSpawn(LootContainer) to scale the freshly generated inventory before the container opens.
Build a plugin with OnLootSpawn
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 OnLootSpawn
Generate