Skip to content
RustPluginGenerator

OnPlayerConnected

OnPlayerConnected is called once by Oxide itself after a client has fully connected and the server has set up its language, CUI snapshot and Covalence player record. It is the first player-scoped hook where the player object is safe to use.

Signature
void OnPlayerConnected(BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer that has just finished connecting. It is a live, connected player object, so you can read net.connection, UserIDString, displayName and send UI or chat to it immediately.

Return value

The return value is ignored. OnPlayerConnected returns void in the game/extension code and Oxide calls it purely for notification, so returning anything has no effect on the connection or on later code.

How it works

This hook is invoked from Oxide's RustCore.IOnPlayerConnected, which runs after the player's language is set from their Steam connection info, a CUI snapshot is sent to the client, and the Covalence player record is attached. It fires exactly once per connection and does not fire on respawn, disconnect or reconnect within the same session, so it is the natural place for per-session setup.

The only argument is the BasePlayer. Use it to read UserIDString, displayName, net.connection.ping or the language string, send a welcome message, open CUI, or apply saved state from your data files. Because Oxide has already configured language before this hook runs, lang.GetMessage with the player's ID returns the correct localized string.

There is no narrowing to do here: the parameter is already the concrete BasePlayer type, and Oxide only calls your method when the argument is an instance of it. Keep the handler fast — it runs on the main thread during the connect flow, and anything slow delays that player's load.

Do not confuse it with OnUserConnected, which fires earlier with the Covalence IPlayer wrapper.

Example plugin: Welcome returning players with a stored playtime greeting

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

namespace Oxide.Plugins
{
    [Info("Connection Welcome", "RustPluginGenerator", "1.0.0")]
    [Description("Greets players when they connect and records their first-seen date.")]
    public class ConnectionWelcome : RustPlugin
    {
        private const string PermExempt = "connectionwelcome.exempt";

        private PluginConfig config;
        private Dictionary<string, string> firstSeen;
        private Timer saveTimer;

        private class PluginConfig
        {
            [JsonProperty("Enable welcome message")]
            public bool Enabled = true;

            [JsonProperty("First visit message cooldown in seconds")]
            public float FirstVisitCooldown = 30f;
        }

        private class StoredData
        {
            public Dictionary<string, string> FirstSeen = new Dictionary<string, string>();
        }

        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>
            {
                ["Welcome"] = "Welcome back, {0}! Have fun on the server.",
                ["FirstVisit"] = "Welcome to the server, {0}! Type /help to see available commands."
            }, 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(PermExempt, this);
            LoadData();
            saveTimer = timer.Every(300f, SaveData);
        }

        private void LoadData()
        {
            var data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
            firstSeen = data?.FirstSeen ?? new Dictionary<string, string>();
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(Name, new StoredData { FirstSeen = firstSeen });
        }

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

            string userId = player.UserIDString;
            if (permission.UserHasPermission(userId, PermExempt)) return;

            string displayName = player.displayName ?? "survivor";

            if (firstSeen.ContainsKey(userId))
            {
                player.ChatMessage(Msg("Welcome", userId, displayName));
                return;
            }

            firstSeen[userId] = DateTime.UtcNow.ToString("yyyy-MM-dd");
            player.ChatMessage(Msg("FirstVisit", userId, displayName));
            SaveData();
        }

        private void Unload()
        {
            saveTimer?.Destroy();
            saveTimer = null;
            SaveData();
        }
    }
}

The plugin keeps a small data file mapping Steam IDs to first-seen timestamps and a stored welcome message flag. In OnPlayerConnected it looks up the player, builds a greeting from the language messages, and sends it with ChatMessage. If the ID is new it records the timestamp and sends the first-visit message instead. The config controls whether the greeting is enabled and the exemption permission lets staff suppress it. Data is written in Unload and on a periodic timer, and the timer reference is destroyed on unload so nothing leaks.

Common use cases

  • Welcome messages and rules broadcast

    Send a localized welcome line, link to your rules, or a short server advertisement to the connecting player. Because the language is already set, lang.GetMessage returns the correct translation.

  • Restore saved player state

    Load a stored balance, rank, kit cooldown or last-known location from oxide/data and apply it to the player as soon as they connect, before they interact with the world.

  • Open an info panel

    Push a CUI panel with server info, vote links or a first-join tutorial. The player's CUI is ready to receive elements by the time this hook fires.

Pitfalls

  • Not the same as OnPlayerSpawn or OnPlayerSleepEnded

    OnPlayerConnected fires once per session, not on respawn. If you need to run code every time a player wakes up or spawns, hook OnPlayerSpawn or OnPlayerSleepEnded instead.

  • Player may still be loading

    The player is connected but may not be fully spawned into the world. Reading transform.position or inventory is generally safe, but avoid teleporting or giving items here if you care about spawn logic — do that on OnPlayerSpawn.

  • Keep it fast

    This runs on the main thread during connect. Long loops, repeated file reads or a slow CUI build delay that player's join. Cache data at OnServerInitialized and only apply it here.

Plugin recipes that use OnPlayerConnected

Build a plugin with OnPlayerConnected

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

Prompt: Welcome messages and rules broadcast using the OnPlayerConnected 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 OnPlayerConnected

Generate