Skip to content
RustPluginGenerator

LoadDefaultConfig

LoadDefaultConfig is an Oxide lifecycle hook called when the plugin needs a fresh default configuration, most often the first time it loads without an existing config file. It is invoked by Oxide itself, not by a patched game method.

Signature
void LoadDefaultConfig()

Return value

Return value is ignored (continue). The original LoadDefaultConfig body is only the hook call, so whether you return null or a value has no effect; the work happens through side effects such as setting the config field and writing the file.

How it works

LoadDefaultConfig is not a game hook. Oxide calls it from Plugin.LoadDefaultConfig when the plugin's config must be created from scratch: on the first server start after installing the plugin, and whenever the config file is missing or unreadable and the plugin falls back to defaults. Its job is to assign your config object a populated instance, typically config = new PluginConfig(); or a call to Config.WriteObject.

The hook takes no parameters and does not receive the player or entity context, so it always runs server-side in the plugin's own lifecycle. You cannot narrow it further; there is only one signature.

Because the hook fires only during load/reload, it is safe to log from it. The usual pattern is LoadDefaultConfig builds defaults, LoadConfig reads oxide/config/<Plugin>.json and repairs a null result by calling LoadDefaultConfig, and SaveConfig writes the object back. Keep defaults realistic so a freshly installed plugin does not spam chat or award oversized values before an admin reviews the file. After editing defaults in source, delete the existing config file or bump the version so Oxide regenerates it.

Example plugin: Create sensible defaults for a starter-kit plugin

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

namespace Oxide.Plugins
{
    [Info("StarterKitDefaults", "RustPluginGenerator", "1.0.0")]
    [Description("Gives each new player a one-time starter kit controlled by a config file.")]
    public class StarterKitDefaults : RustPlugin
    {
        private const string DataFileName = "StarterKitDefaults/players";

        private PluginConfig config;
        private HashSet<ulong> grantedPlayers;

        private class PluginConfig
        {
            [JsonProperty("Enable starter kit")]
            public bool Enabled { get; set; } = true;

            [JsonProperty("Item shortname")]
            public string ItemShortname { get; set; } = "supply.signal";

            [JsonProperty("Amount")]
            public int Amount { get; set; } = 5;

            [JsonProperty("Give only once per player")]
            public bool OncePerPlayer { get; set; } = true;

            [JsonProperty("Broadcast message to the player")]
            public bool NotifyPlayer { get; set; } = true;
        }

        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>
            {
                ["KitGiven"] = "You received your starter kit: {0} x {1}",
                ["KitDisabled"] = "Starter kits are currently disabled."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args) =>
            string.Format(lang.GetMessage(key, this, userId), args);

        private void Init()
        {
            LoadData();
        }

        private void LoadData()
        {
            grantedPlayers = Interface.Oxide.DataFileSystem.ReadObject<HashSet<ulong>>(DataFileName) ?? new HashSet<ulong>();
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            if (!config.Enabled || player == null || player.IsNpc) return;

            if (config.OncePerPlayer && grantedPlayers.Contains(player.userID))
            {
                return;
            }

            ItemDefinition definition = ItemManager.FindItemDefinition(config.ItemShortname);
            if (definition == null)
            {
                return;
            }

            int amount = Mathf.Max(1, config.Amount);
            Item item = ItemManager.CreateByName(config.ItemShortname, amount);
            if (item == null) return;

            player.GiveItem(item);

            if (config.OncePerPlayer)
            {
                grantedPlayers.Add(player.userID);
            }

            if (config.NotifyPlayer)
            {
                player.ChatMessage(Msg("KitGiven", player.UserIDString, amount, definition.displayName.english));
            }
        }

        private void Unload()
        {
            Interface.Oxide.DataFileSystem.WriteObject(DataFileName, grantedPlayers);
        }
    }
}

The plugin gives every newly connected player a welcome kit once. PluginConfig holds the enable flag, item shortname, amount and the once-per-player switch. LoadDefaultConfig assigns a fresh PluginConfig so a missing config file still starts with usable values; LoadConfig reads from oxide/config and calls LoadDefaultConfig if the object deserializes to null; SaveConfig persists. OnPlayerConnected checks the config, verifies the item shortname exists, grants the item with GiveItem and records the player id in a HashSet<ulong> (persisted via the data file), so reconnects do not re-grant. Unload saves the data file.

Common use cases

  • Seed defaults on first install

    Assign a populated config object so a fresh install never runs with null fields. This is the standard use of the hook.

  • Repair a corrupt config

    Call LoadDefaultConfig() from LoadConfig when Config.ReadObject<T>() returns null, then SaveConfig to overwrite the broken file.

  • Reset after schema changes

    Bump the plugin version and let LoadDefaultConfig supply new fields; existing keys are read from disk, so add a version field if you need to migrate.

Pitfalls

  • It does not merge with existing files

    Oxide only calls this hook when defaults are needed. Editing a shortname or amount in source does nothing until the existing oxide/config file is deleted or migrated.

  • Network or entity calls belong here not

    The hook runs before the server is fully initialized. Do not spawn entities, message players or reference BasePlayer.activePlayerList; do that in OnServerInitialized.

  • Forgot to save

    If you set the field but never call SaveConfig, the file is not written and defaults are rebuilt next restart. The base LoadDefaultConfig does not write the file for you.

Build a plugin with LoadDefaultConfig

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

Prompt: Seed defaults on first install using the LoadDefaultConfig 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 LoadDefaultConfig

Generate