How to make a Rust give kit plugin (admin /givekit command)
This plugin adds an admin /givekit command plus a matching console command that hands a config-defined kit to any online or sleeping player, bypassing cooldowns. It needs no game hooks beyond Init and Loaded-style startup checks and reads kit contents from the config file.
Kit plugins usually guard rewards behind cooldowns, permission groups and UI flows, which is exactly what you do not want when a tournament is starting or a player lost their gear to a bug. Support staff need a direct way to hand out a known set of items on demand. The plugin below stores kits in oxide/config/GiveKit.json, each kit a list of Shortname, Amount and Skin entries. /givekit <player> <kit> and the console form givekit <player> <kit> look the player up with BasePlayer.FindAwakeOrSleeping, resolve the kit, build the items with ItemManager.CreateByName and call player.GiveItem. Nothing checks cooldowns and nothing is taken from the player. Kits are validated at startup so a bad shortname produces a warning before an event instead of a silent failure mid-event.
The plugin code
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("GiveKit", "RustPluginGenerator", "1.0.0")]
[Description("Adds an admin chat and console command that gives config-defined kits to players.")]
public class GiveKit : RustPlugin
{
private const string PermUse = "givekit.use";
private PluginConfig config;
private class KitItem
{
[JsonProperty("Shortname")]
public string Shortname { get; set; } = "wood";
[JsonProperty("Amount")]
public int Amount { get; set; } = 1;
[JsonProperty("Skin")]
public ulong Skin { get; set; }
}
private class PluginConfig
{
[JsonProperty("Kits")]
public Dictionary<string, List<KitItem>> Kits { get; set; } = new Dictionary<string, List<KitItem>>(StringComparer.OrdinalIgnoreCase)
{
["starter"] = new List<KitItem>
{
new KitItem { Shortname = "rock", Amount = 1 },
new KitItem { Shortname = "torch", Amount = 1 },
new KitItem { Shortname = "bandage", Amount = 5 },
new KitItem { Shortname = "wood", Amount = 500 },
new KitItem { Shortname = "metal.fragments", Amount = 100 }
}
};
}
protected override void LoadDefaultConfig() => config = new PluginConfig();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<PluginConfig>();
if (config == null) throw new Exception();
if (config.Kits == null) config.Kits = new Dictionary<string, List<KitItem>>(StringComparer.OrdinalIgnoreCase);
}
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>
{
["KitGiven"] = "Gave kit '{0}' ({1} items) to {2}.",
["KitMissing"] = "No kit named '{0}' exists in the config.",
["PlayerNotFound"] = "No player found matching '{0}'.",
["NoPermission"] = "You do not have permission to use this command.",
["Usage"] = "Usage: /givekit <player> <kit>",
["ItemMissing"] = "Kit '{0}' contains an unknown item '{1}', giving aborted."
}, 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);
}
private void OnServerInitialized()
{
foreach (var kit in config.Kits)
{
if (kit.Value == null) continue;
foreach (var entry in kit.Value)
{
if (entry == null || string.IsNullOrEmpty(entry.Shortname)) continue;
if (ItemManager.FindItemDefinition(entry.Shortname) == null)
PrintWarning($"Kit '{kit.Key}' references unknown item '{entry.Shortname}'");
}
}
}
[ChatCommand("givekit")]
private void CmdGiveKit(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermUse))
{
SendReply(player, Msg("NoPermission", player.UserIDString));
return;
}
if (args == null || args.Length < 2)
{
SendReply(player, Msg("Usage", player.UserIDString));
return;
}
Run(player, args[0], args[1]);
}
[ConsoleCommand("givekit")]
private void CcmdGiveKit(ConsoleSystem.Arg arg)
{
var caller = arg.Player();
if (caller != null && !permission.UserHasPermission(caller.UserIDString, PermUse))
{
arg.ReplyWith(Msg("NoPermission", caller.UserIDString));
return;
}
if (arg.Args == null || arg.Args.Length < 2)
{
arg.ReplyWith(Msg("Usage", caller?.UserIDString));
return;
}
Run(caller, arg.Args[0].ToString(), arg.Args[1].ToString());
}
private void Run(BasePlayer caller, string targetArg, string kitArg)
{
var target = BasePlayer.FindAwakeOrSleeping(targetArg);
if (target == null)
{
Reply(caller, Msg("PlayerNotFound", caller?.UserIDString, targetArg));
return;
}
List<KitItem> kit;
if (!TryGetKit(kitArg, out kit))
{
Reply(caller, Msg("KitMissing", caller?.UserIDString, kitArg));
return;
}
var given = GiveKitToPlayer(target, kit);
if (given < 0)
{
Reply(caller, Msg("ItemMissing", caller?.UserIDString, kitArg, "?"));
return;
}
Reply(caller, Msg("KitGiven", caller?.UserIDString, kitArg, given, target.displayName));
}
private bool TryGetKit(string name, out List<KitItem> kit)
{
kit = null;
if (string.IsNullOrEmpty(name) || config.Kits == null) return false;
foreach (var pair in config.Kits)
{
if (string.Equals(pair.Key, name, StringComparison.OrdinalIgnoreCase))
{
kit = pair.Value;
return kit != null;
}
}
return false;
}
private int GiveKitToPlayer(BasePlayer player, List<KitItem> kit)
{
var given = 0;
foreach (var entry in kit)
{
if (entry == null || string.IsNullOrEmpty(entry.Shortname)) continue;
var amount = entry.Amount < 1 ? 1 : entry.Amount;
var item = ItemManager.CreateByName(entry.Shortname, amount, entry.Skin);
if (item == null)
{
if (given > 0) player.ChatMessage(Msg("KitGiven", player.UserIDString, "?", given, player.displayName));
return -1;
}
player.GiveItem(item);
given++;
}
Interface.Oxide.LogInfo($"[GiveKit] {player.displayName} ({player.UserIDString}) received a kit with {given} item stacks");
return given;
}
private void Reply(BasePlayer caller, string message)
{
if (caller != null)
SendReply(caller, message);
else
Puts(message);
}
}
}Hooks used: OnServerInitialized
Config file
Created automatically on first load at oxide/config/GiveKit.json.
{
"Kits": {
"starter": [
{
"Shortname": "rock",
"Amount": 1,
"Skin": 0
},
{
"Shortname": "torch",
"Amount": 1,
"Skin": 0
},
{
"Shortname": "bandage",
"Amount": 5,
"Skin": 0
},
{
"Shortname": "wood",
"Amount": 500,
"Skin": 0
},
{
"Shortname": "metal.fragments",
"Amount": 100,
"Skin": 0
}
]
}
}Commands and permissions
| Command | What it does | Permission |
|---|---|---|
/givekit <player> <kit> | Gives the named kit to the target player. Player can be a display name or a Steam ID. | givekit.use |
givekit <player> <kit> | Console form for the server console and RCON. Same arguments and permission behaviour as the chat command. | givekit.use |
| Permission | Grants |
|---|---|
givekit.use | Allows using /givekit and the givekit console command. |
How the code works
Describe kits in the config
The
PluginConfigclass holds aKitsdictionary keyed by kit name, each value a list ofKitItementries withShortname,AmountandSkinproperties.LoadDefaultConfigreturns a workingstarterkit.LoadConfigreads the object back withConfig.ReadObject<PluginConfig>, falls back to defaults when parsing throws, andSaveConfigwrites it out, so on first run the file is created with the default kit. Admins editoxide/config/GiveKit.jsonand reload the plugin to pick up changes.Validate kits at startup
OnServerInitializedwalks every entry ofconfig.Kitsand callsItemManager.FindItemDefinition(entry.Shortname)for eachKitItemthat has a non-empty shortname. Unknown shortnames log a warning naming the kit and the item, which points straight at the config line to fix. Running the check once at load keeps the command path free of repeated lookups and gives admins a clear error before an event instead of after it.Resolve the target player
BasePlayer.FindAwakeOrSleepingaccepts a partial display name or a Steam ID and returns the player or null. Sleeping players are included because support often hands out replacement gear before the owner logs back in. When the result is null,Runreplies with thePlayerNotFoundlang key. Chat callers get it throughSendReply; console callers get it througharg.ReplyWithwhen a player is attached, otherwise throughPutsinReply.Build and hand over items
GiveKitToPlayerloops the resolved list, callsItemManager.CreateByName(Shortname, Amount, Skin)and passes each item toplayer.GiveItem. Creating an item returns null when the shortname is unknown, and the method then returns -1 so the caller can report theItemMissingkey. Items already given earlier in the loop stay with the player, so the kit is partial when this happens. The plugin never strips or takes items, so it is safe to run repeatedly.Register both command forms
[ChatCommand("givekit")]handles the in-game path with parametersBasePlayer,stringandstring[];[ConsoleCommand("givekit")]handles the server console and RCON throughConsoleSystem.Arg. Both checkpermission.UserHasPermissionand require two arguments inargsorarg.Args. The console handler usesarg.Player()for the caller, which is null from the server console, so the permission check only applies when a player typed it.Messages in lang
All replies live in
LoadDefaultMessagesunder keys such asKitGiven,KitMissing,PlayerNotFound,NoPermission,UsageandItemMissing, and go through theMsghelper that wrapslang.GetMessage. Because the helper takes a user id, the same keys produce per-player translations for chat replies and the same English text for console output. No player-facing text is hard-coded in the command handlers.
Install it on your server
Save GiveKit.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/GiveKit.json(Carbon:carbon/configs/GiveKit.json). After editing, reload it:oxide.reload GiveKit c.reload GiveKit # CarbonGrant the permission
Give it to every player, or swapdefaultfor a group such asvip:oxide.grant group default givekit.use c.grant group default givekit.use # Carbon
Variations
Each one opens the generator with a ready prompt you can tweak.
Send the kit to a whole team
Resolve the target's team with RelationshipManager and give the kit to every member that is awake or sleeping.
Generate this versionLog every kit handout
Persist a per-player history of who received which kit and when, using the Oxide data file system.
Generate this versionChat kit list
Add a /kits command that prints the configured kit names so staff know the exact argument to type.
Generate this version
FAQ
Does this plugin respect kit cooldowns?
No. It sits outside any cooldown system by design, because its purpose is support and event handouts. If you also run a public kit plugin, keep this command permission-gated to staff so players cannot use it to skip cooldowns on the other plugin's kits.
How do I install it on Oxide or Carbon?
Put the compiled GiveKit.cs in oxide/plugins, run oxide.reload GiveKit from the server console, then grant givekit.use to your staff group. Carbon loads the same file from the same folder. Edit oxide/config/GiveKit.json to define kits and reload the plugin to apply changes.
What happens if an item shortname is wrong?
OnServerInitialized logs a warning for each unknown shortname so you can fix it before using the kit. If it still slips through, ItemManager.CreateByName returns null and GiveKitToPlayer returns -1. Items before the bad entry were already given, the caller sees the ItemMissing message, and the target player receives a KitGiven message with a ? kit name.
Can I give a kit to an offline player?
Only if the player entity exists as a sleeper. FindAwakeOrSleeping finds sleeping players by name or Steam ID and player.GiveItem places items into their inventory for the next login. Players with no entity on the map at all are reported as not found.
Do skins work on kit items?
Yes. Each KitItem has a Skin ulong property passed as the third argument to ItemManager.CreateByName, so workshop skin ids carry over. Use 0 for the default skin. Invalid skin ids still apply the item, the client simply shows the default appearance.
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
- 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
- One per wipe kitsGives players configurable kits that can be claimed once per wipe, tracked in a data file cleared when the server starts a new map save, using theโฆOnNewSave
Last updated Oct 26, 2026.
Customize give kit command
Customize