How to make a Rust wipe day kit plugin (Oxide)
Adds a one-time starter kit that can only be claimed during the first N hours after a map wipe, using OnNewSave to start the window and /wipekit to claim or show it is closed.
Wipe day crowds are good for a server, but hand-adding a starter kit to every fresh wipe is tedious and error-prone. The usual problems: the kit gets claimed weeks later by a player who just found the server, or you forget to enable it and the wipe starts without one. This plugin solves both by anchoring the claim window to the actual wipe.
When Rust calls OnNewSave, the plugin records the current Unix timestamp in oxide/data/WipeDayKit.json. From then until the configured window closes, any player can run /wipekit once to receive the configured items. After the window ends, /wipekit reports that claiming is closed. The window length, the item list, and the claimed player IDs all live in the config and data files, so you can change loadouts between wipes without touching code.
The plugin code
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Wipe Day Kit", "RustPluginGenerator", "1.0.0")]
[Description("Gives players a one-time kit that can only be claimed during the first N hours after a wipe.")]
public class WipeDayKit : RustPlugin
{
private const string PermUse = "wipedaykit.use";
private PluginConfig config;
private StoredData data;
private class PluginConfig
{
[JsonProperty("Window hours after wipe")]
public int WindowHours = 48;
[JsonProperty("Items")]
public List<KitItem> Items = new List<KitItem>
{
new KitItem { Shortname = "scrap", Amount = 500 },
new KitItem { Shortname = "stone.pickaxe", Amount = 1 },
new KitItem { Shortname = "stone.hatchet", Amount = 1 },
new KitItem { Shortname = "bandage", Amount = 3 }
};
}
private class KitItem
{
[JsonProperty("Shortname")]
public string Shortname = "scrap";
[JsonProperty("Amount")]
public int Amount = 1;
[JsonProperty("Skin")]
public ulong Skin = 0;
}
private class StoredData
{
[JsonProperty("Start unix")]
public long StartUnix = 0;
[JsonProperty("Claimed user ids")]
public List<ulong> Claimed = new List<ulong>();
}
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>
{
["NoPermission"] = "You do not have permission to claim the wipe day kit.",
["AlreadyClaimed"] = "You already claimed your wipe day kit.",
["WindowClosed"] = "The wipe day kit window has closed.",
["WindowOpen"] = "Wipe day kit available. Time left: {0}h {1}m.",
["Claimed"] = "Wipe day kit claimed. Have fun!",
["ClaimFailed"] = "Your kit could not be granted right now. Try again later.",
["NoItems"] = "No items were given. Check your inventory space or contact an admin."
}, 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(PermUse, this);
LoadData();
}
private void OnServerInitialized()
{
if (data == null) LoadData();
if (data.StartUnix <= 0)
{
data.StartUnix = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
Interface.Oxide.DataFileSystem.WriteObject(Name, data);
}
}
private void Unload()
{
SaveData();
}
private void LoadData()
{
try
{
data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
}
catch
{
data = null;
}
if (data == null) data = new StoredData();
if (data.Claimed == null) data.Claimed = new List<ulong>();
}
private void SaveData()
{
if (data != null) Interface.Oxide.DataFileSystem.WriteObject(Name, data);
}
private void OnNewSave(string strFilename)
{
LoadData();
data.StartUnix = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
data.Claimed.Clear();
SaveData();
}
[ChatCommand("wipekit")]
private void CmdWipeKit(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermUse))
{
SendReply(player, Msg("NoPermission", player.UserIDString));
return;
}
if (data == null) LoadData();
if (data.Claimed.Contains(player.userID.Get()))
{
SendReply(player, Msg("AlreadyClaimed", player.UserIDString));
return;
}
double elapsed = (DateTimeOffset.UtcNow.ToUnixTimeSeconds() - data.StartUnix) / 3600.0;
if (data.StartUnix <= 0 || elapsed < 0 || elapsed > config.WindowHours)
{
SendReply(player, Msg("WindowClosed", player.UserIDString));
return;
}
double remaining = config.WindowHours - elapsed;
int hours = (int)remaining;
int minutes = Mathf.Max(0, (int)((remaining - hours) * 60));
SendReply(player, Msg("WindowOpen", player.UserIDString, hours, minutes));
if (GiveKit(player))
{
data.Claimed.Add(player.userID.Get());
SaveData();
SendReply(player, Msg("Claimed", player.UserIDString));
}
else
{
SendReply(player, Msg("ClaimFailed", player.UserIDString));
}
}
private bool GiveKit(BasePlayer player)
{
int given = 0;
foreach (var entry in config.Items)
{
if (entry == null || string.IsNullOrEmpty(entry.Shortname)) continue;
int amount = Mathf.Max(1, entry.Amount);
Item item = ItemManager.CreateByName(entry.Shortname, amount, entry.Skin);
if (item == null)
{
PrintWarning($"Unknown shortname in config: {entry.Shortname}");
continue;
}
player.GiveItem(item);
given++;
}
if (given == 0)
{
SendReply(player, Msg("NoItems", player.UserIDString));
return false;
}
return true;
}
}
}Hooks used: OnServerInitialized, OnNewSave
Config file
Created automatically on first load at oxide/config/WipeDayKit.json.
{
"Window hours after wipe": 48,
"Items": [
{
"Shortname": "scrap",
"Amount": 500,
"Skin": 0
},
{
"Shortname": "stone.pickaxe",
"Amount": 1,
"Skin": 0
},
{
"Shortname": "stone.hatchet",
"Amount": 1,
"Skin": 0
},
{
"Shortname": "bandage",
"Amount": 3,
"Skin": 0
}
],
"Start unix": 0,
"Claimed user ids": []
}Commands and permissions
| Command | What it does | Permission |
|---|---|---|
/wipekit | Claims the wipe day kit, or tells the player the window is closed or already claimed. | wipedaykit.use |
| Permission | Grants |
|---|---|
wipedaykit.use | Grants access to the /wipekit command and the claim. |
How the code works
Detecting the wipe with OnNewSave
OnNewSave(string strFilename)fires when the server saves a brand new map. The hook loads the data file, setsdata.StartUnixtoDateTimeOffset.UtcNow.ToUnixTimeSeconds(), and clearsdata.Claimed. It then writesoxide/data/WipeDayKit.json.OnServerInitializedcovers the fresh-install case: ifdata.StartUnixis still zero, it stores the current time so the window starts now rather than never.The claim window
The
Window hours after wipekey in the config controls how long players can claim./wipekitsubtractsdata.StartUnixfrom the current Unix time and divides by 3600 to get elapsed hours. Ifdata.StartUnixis zero, or if the result is negative or larger thanWindowHours, the player gets theWindowClosedmessage and no items are granted.One kit per player
data.Claimedis aList<ulong>of player IDs. Before granting items, the command checksdata.Claimed.Contains(player.userID.Get())and stops if true. A successful grant adds the ID and callsSaveData, which writes the file. To let everybody claim again without wiping, deleteoxide/data/WipeDayKit.jsonand reload the plugin.Granting the items
The
Itemslist in the config holds objects withShortname,Amount, andSkin.GiveKitwalks the list, callsItemManager.CreateByName(shortname, amount, skin)for each entry, and passes the result toplayer.GiveItem(item). Entries whose shortname is unknown print a warning and are skipped. If no items get created at all, the player is toldNoItemsand stays unclaimed.The /wipekit command
Initregisters thewipedaykit.usepermission, and[ChatCommand("wipekit")]marksCmdWipeKitas the handler. Before doing any work, the command checkspermission.UserHasPermissionand sendsNoPermissionif it fails. Grant the permission on the default group withoxide.grant group default wipedaykit.use, or manage it per player with a permission plugin.
Install it on your server
Save WipeDayKit.cs
Keep the file name exactly as the class name. Oxide matches them.Upload it to the plugins folder
Oxide:oxide/plugins/. Carbon:carbon/plugins/. The server compiles and loads it within a few seconds, no restart needed.Edit the config if you want
On first load the default config is written tooxide/config/WipeDayKit.json(Carbon:carbon/configs/WipeDayKit.json). After editing, reload it:oxide.reload WipeDayKit c.reload WipeDayKit # CarbonGrant the permission
Give it to every player, or swapdefaultfor a group such asvip:oxide.grant group default wipedaykit.use c.grant group default wipedaykit.use # Carbon
Variations
Each one opens the generator with a ready prompt you can tweak.
In-game admin reset
Let an admin clear one player's claim or restart the window without touching files.
Generate this versionTiered kits
Different loadouts for VIPs and regular players.
Generate this versionWipe announcement
Broadcast to the whole server that the kit window just opened.
Generate this version
FAQ
Does the window restart on every server restart?
No. Only OnNewSave resets data.StartUnix, and that hook fires on a new map save. A plain restart just reloads the stored timestamp from oxide/data/WipeDayKit.json, so the remaining hours keep counting down across restarts during wipe day.
How do I install this on Oxide or Carbon?
Drop WipeDayKit.cs into oxide/plugins/ on Oxide, or the same folder on Carbon (Carbon loads Oxide plugins). Reload the plugin; it writes oxide/config/WipeDayKit.json and oxide/data/WipeDayKit.json. Edit the config and run oxide.reload WipeDayKit.
What happens if there is no room in the player's inventory?
player.GiveItem drops overflow next to the player, and the plugin counts the entry as given. The claim is still recorded, so the player cannot double dip. If every shortname in Items is wrong, GiveKit returns false and the player remains unclaimed with a NoItems message.
How do I test without wiping the map?
Stop the server or reload the plugin, delete oxide/data/WipeDayKit.json, and reload. OnServerInitialized then sets data.StartUnix to the current time with an empty claimed list. Run /wipekit twice to confirm the first claim succeeds and the second is rejected.
Customize it for your server
Change the reward, add a cooldown, restrict it to VIPs. Start from this prompt and edit anything.
Edit the prompt on the next screen. 2 free plugins a month, no card.
More kits plugins
- Give kit commandThis plugin adds an admin /givekit command plus a matching console command that hands a config-defined kit to any online or sleeping player,โฆOnServerInitialized
- Group respawn kitsGives each player a respawn loadout based on the highest-priority Oxide group they belong to.OnPlayerRespawned
- Kits with cooldownsAdds permission-aware kits with per-kit cooldowns and per-wipe use limits.OnServerInitializedOnNewSave
Last updated Oct 26, 2026.
Customize wipe day kit
Customize