OnXmasStockingFill
OnXmasStockingFill is called when a Christmas stocking is empty and about to be filled with its default loot. Returning a non-null value suppresses the vanilla fill.
object OnXmasStockingFill(Stocking stocking)Parameters
| Parameter | Type | Description |
|---|---|---|
stocking | Stocking | The Stocking entity whose loot is about to be generated. Use its inventory, transform.position, OwnerID and net.ID to inspect or replace the contents. |
Return value
Return null (or let the method fall through) to let the vanilla SpawnLoot routine run and fill the stocking with default loot. Return any non-null value to skip the original fill entirely; the returned object is discarded because the patched method returns void.
How it works
The hook fires from Stocking.SpawnLoot, and only when two conditions hold: the stocking's inventory is not null and IsEmpty() returns true. That means it runs when a stocking is first made lootable on a server running the Christmas event, not every time someone opens it. If the container already holds items, the hook is never called.
The only parameter is the Stocking entity itself. Because it derives from StorageContainer, you can read stocking.inventory (an ItemContainer), clear it, or push items into it with ItemManager.CreateByName and MoveToContainer. You can also use OwnerID to find the owner and transform.position for location-based logic.
The hook is called on every empty stocking that attempts a fill, so it can fire many times during the holiday period. Keep the body cheap: no Puts, no per-entity network updates. If you want a specific type of stocking, narrow the parameter to a subclass, but in practice the base Stocking type is what you will always receive here.
Example plugin: Fill Christmas stockings with a configurable custom loot table
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Custom Stocking Loot", "RustPluginGenerator", "1.0.0")]
[Description("Fills Christmas stockings with a configurable loot table instead of the default one.")]
public class CustomStockingLoot : RustPlugin
{
private class LootEntry
{
[JsonProperty("Shortname")]
public string Shortname = "scrap";
[JsonProperty("Amount")]
public int Amount = 25;
}
private class PluginConfig
{
[JsonProperty("Use custom loot table")]
public bool Enabled = true;
[JsonProperty("Loot entries")]
public List<LootEntry> Loot = new List<LootEntry>
{
new LootEntry { Shortname = "scrap", Amount = 50 },
new LootEntry { Shortname = "xmas.present.small", Amount = 1 },
new LootEntry { Shortname = "xmas.present.medium", Amount = 1 }
};
}
private PluginConfig config;
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 OnServerInitialized()
{
if (!config.Enabled || config.Loot == null) return;
foreach (var entry in config.Loot)
{
if (string.IsNullOrEmpty(entry.Shortname)) continue;
var def = ItemManager.FindItemDefinition(entry.Shortname);
if (def == null)
{
PrintWarning($"Unknown item shortname in config: {entry.Shortname}");
continue;
}
if (entry.Amount > def.stackable)
{
PrintWarning($"{entry.Shortname} amount {entry.Amount} exceeds stack size {def.stackable}");
}
}
}
private object OnXmasStockingFill(Stocking stocking)
{
if (!config.Enabled || stocking == null) return null;
if (stocking.inventory == null) return null;
var entries = config.Loot;
if (entries == null || entries.Count == 0) return null;
foreach (var entry in entries)
{
var def = ItemManager.FindItemDefinition(entry.Shortname);
if (def == null) continue;
int remaining = Mathf.Max(1, entry.Amount);
while (remaining > 0)
{
int amount = Mathf.Min(remaining, def.stackable);
var item = ItemManager.CreateByName(entry.Shortname, amount);
if (item == null) break;
if (!item.MoveToContainer(stocking.inventory))
{
item.Remove();
break;
}
remaining -= amount;
}
}
stocking.inventory.MarkDirty();
return true;
}
}
}The plugin defines a config list of shortnames and amounts. When OnXmasStockingFill fires, it checks the stocking's inventory, then inserts each configured item, stacking it if needed and otherwise creating a new item via ItemManager.CreateByName. A stack-size warning is printed at load time for entries that exceed the item's stackable value. The hook returns true so the vanilla loot table never runs, giving admins full control. Reload the plugin after editing the config to apply new entries, and leave the list empty to keep stockings vanilla.
Common use cases
Custom loot tables
Replace the default holiday loot with server-specific items such as scrap, components or event currency. Returning a value stops the vanilla fill.
Owner-restricted rewards
Read
stocking.OwnerIDto give the stocking's owner a personal reward, for example a gift box tied to their Steam ID.Anti-farm tuning
Reduce the value of stockings during high-population events by filling them with mostly scrap or low-tier components instead of premium items.
Pitfalls
Hook only fires on empty stockings
SpawnLootis guarded byIsEmpty(). If anything already put an item in the container, your hook will not run and the vanilla fill is also skipped for that pass.Do not stack over the item limit
Custom amounts must respect
item.info.stackable. Overfilled stacks are clamped or dropped by the container, so split large rewards into severalGiveItem/MoveToContainercalls.Return value is not a boolean result
The patched method returns void, so the object you return only acts as a flag. Returning
falsestill suppresses the vanilla fill because it is non-null. Returnnullto keep vanilla behavior.
Build a plugin with OnXmasStockingFill
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 OnXmasStockingFill
Generate