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.
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
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.RegisterPermissioninInitfor 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.serverEntitieshere can return empty results or throw half-initialized errors.Throwing marks the plugin as failed
An uncaught exception in
Initis logged by Oxide and stored as a plugin error. Wrap risky calls in try/catch or defer them toOnServerInitialized.Not the same as OnServerInitialized
Initfires per plugin when it is added;OnServerInitializedfires when the server is actually ready. UseInitfor registration,OnServerInitializedfor work that needs the world.
Build a plugin with Init
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 Init
Generate