Skip to content
RustPluginGenerator

Init

Init is called by Oxide once while the plugin is being added to the plugin manager, before any hook subscriptions or world data are available to it. It is the earliest reliable place to register permissions and run setup that must exist before other hooks fire.

Signature
void Init()

Return value

Init returns void, so any value is discarded. The call site does not use the result; throwing is the only way to affect behavior, and a thrown exception causes Oxide to log the failure and record a plugin error.

How it works

Oxide invokes Init from CSPlugin.HandleAddedToManager, immediately after the plugin subscribes to its hooks and before the base manager finishes wiring the plugin in. There are no parameters. Because it runs this early, it is the standard place to register permissions with permission.RegisterPermission and do throwaway setup that does not depend on players, entities or the server world. If Init throws, Oxide logs the exception and marks the plugin as failed to initialize, so keep the method small and defensive.

Do not expect the server to be ready: no players are connected, maps and save data may not be loaded, and other plugins may not have started. That is what OnServerInitialized is for. Keep heavy work, config-dependent world changes and anything touching BasePlayer.activePlayerList out of Init. Registration calls here are cheap and safe, which is why permission setup belongs here rather than in a timer or command handler.

Example plugin: Register a teleport permission on startup

InitPermissionSetup.cs
using System.Collections.Generic;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Init Permission Setup", "RustPluginGenerator", "1.0.0")]
    [Description("Registers a teleport permission in Init and demonstrates a permission-gated chat command")]
    public class InitPermissionSetup : RustPlugin
    {
        private const string PermUse = "initpermissionsetup.tp";

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["NoPermission"] = "You do not have permission to use this command.",
                ["Granted"] = "You have access to the teleport command.",
                ["Usage"] = "Usage: /tp <player name>"
            }, this);
        }

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

        [ChatCommand("tp")]
        private void CmdTp(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;

            if (!permission.UserHasPermission(player.UserIDString, PermUse))
            {
                player.ChatMessage(Msg("NoPermission", player.UserIDString));
                return;
            }

            if (args == null || args.Length < 1)
            {
                player.ChatMessage(Msg("Usage", player.UserIDString));
                return;
            }

            var target = BasePlayer.FindAwakeOrSleeping(args[0]);
            if (target == null)
            {
                player.ChatMessage(Msg("Usage", player.UserIDString));
                return;
            }

            player.Teleport(target.transform.position);
            player.ChatMessage(Msg("Granted", player.UserIDString));
            Puts($"{player.displayName} teleported to {target.displayName}");
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player != null && player.IsConnected)
                {
                    player.ChatMessage("Teleport plugin reloaded.");
                }
            }
        }
    }
}

The plugin registers a initpermissionsetup.tp permission inside Init so the permission exists as soon as the plugin is added to the manager. UseTp is a chat command that checks the permission with permission.UserHasPermission and reports a localized message either way. Unload demonstrates the cleanup hook. No world state is touched in Init, only the permission registry, which is available at that point. The example keeps messages in the language file so the response text can be translated without touching code.

Common use cases

  • Registration of permissions

    Call permission.RegisterPermission in Init for every permission the plugin checks, so admin tools see the full list the moment the plugin loads.

  • Sanity checks that fail fast

    Verify that required config values or plugin references exist and log a clear warning if not, so a misconfigured plugin is obvious in the console at load time.

  • Seeding in-memory state

    Initialize dictionaries, lists and lookup tables that hooks will use later, avoiding null checks scattered through frequently fired hooks.

Pitfalls

  • Do not touch the world in Init

    Entities, players and save data may not be ready. Spawning, teleporting or iterating BaseNetworkable.serverEntities here can return empty results or throw half-initialized errors.

  • Throwing marks the plugin as failed

    An uncaught exception in Init is logged by Oxide and stored as a plugin error. Wrap risky calls in try/catch or defer them to OnServerInitialized.

  • Not the same as OnServerInitialized

    Init fires per plugin when it is added; OnServerInitialized fires when the server is actually ready. Use Init for registration, OnServerInitialized for work that needs the world.

Build a plugin with Init

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

Prompt: Registration of permissions using the Init 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 Init

Generate