Skip to content
RustPluginGenerator

OnPlayerSleepEnded

OnPlayerSleepEnded is called when a player finishes the wake-up routine and control returns to their character, after the game has refreshed their main, belt and wear inventories.

Signature
void OnPlayerSleepEnded(BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer who just finished waking up. Their inventory containers have already been refreshed when this hook fires, and the player is controlled again by the client.

Return value

The return value is ignored. The injection calls the hook and continues with the rest of EndSleeping (EAC logging and ping sync), so returning null or any value changes nothing.

How it works

This hook fires from BasePlayer.EndSleeping, the method the server runs when a sleeping player becomes active again. That happens when the player receives a respawn/wake signal from the client, for example after selecting a sleeping bag or bed or reconnecting into their existing body. By the time the hook runs, inventory.containerMain, containerBelt and containerWear have already been marked dirty, so the client-side inventory is in sync with the server.

The single parameter is the freshly awake BasePlayer. Use it to read position, team, health or inventory state and react. Because the hook fires after waking rather than after spawning, it is the right place for logic that should apply every time a player stands up: welcome-back messages, scheduled rewards, region checks, re-applying buffs or vanish states, or kicking a player who woke inside a blocked area. It fires once per wake event, not per frame, so light work here is safe. Do heavier work behind a short timer if it touches many entities.

Declaring the parameter as BasePlayer is the natural choice; a broader type offers no benefit since the argument is always a player.

Example plugin: Welcome-back message with a cooldown-limited reward

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

namespace Oxide.Plugins
{
    [Info("Sleep End Reward", "RustPluginGenerator", "1.0.0")]
    [Description("Greets players when they wake up and grants a cooldown-limited reward.")]
    public class SleepEndReward : RustPlugin
    {
        private const string PermReward = "sleependreward.reward";

        private PluginConfig config;
        private Dictionary<string, long> lastReward;

        private class PluginConfig
        {
            [JsonProperty("Welcome message enabled")]
            public bool WelcomeEnabled = true;

            [JsonProperty("Reward item shortname")]
            public string RewardShortname = "scrap";

            [JsonProperty("Reward amount")]
            public int RewardAmount = 25;

            [JsonProperty("Reward cooldown in seconds")]
            public long CooldownSeconds = 43200;
        }

        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}. You are at {1}.",
                ["Reward"] = "You received {0} x {1}.",
                ["RewardCooldown"] = "Your wake-up reward is on cooldown."
            }, 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(PermReward, this);
            lastReward = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, long>>(Name) ?? new Dictionary<string, long>();
        }

        private void Unload()
        {
            Interface.Oxide.DataFileSystem.WriteObject(Name, lastReward);
        }

        private void OnPlayerSleepEnded(BasePlayer player)
        {
            if (player == null || !player.IsConnected) return;

            string userId = player.UserIDString;
            Vector3 pos = player.transform.position;

            // Give the client a moment to finish the wake transition before chatting.
            timer.Once(1f, () =>
            {
                if (player == null || !player.IsConnected) return;

                if (config.WelcomeEnabled)
                    player.ChatMessage(Msg("Welcome", userId, player.displayName, $"({(int)pos.x}, {(int)pos.z})"));

                if (!permission.UserHasPermission(userId, PermReward)) return;

                long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                long last;
                if (lastReward.TryGetValue(userId, out last) && now - last < config.CooldownSeconds)
                {
                    player.ChatMessage(Msg("RewardCooldown", userId));
                    return;
                }

                Item item = ItemManager.CreateByName(config.RewardShortname, config.RewardAmount);
                if (item == null) return;

                player.GiveItem(item);
                lastReward[userId] = now;
                player.ChatMessage(Msg("Reward", userId, config.RewardAmount, item.info.displayName.english));
            });
        }
    }
}

The plugin listens for OnPlayerSleepEnded and, for each waking player, resolves their permission group and sends a localized welcome-back message through the language file. If they hold the reward permission and their per-player cooldown stored in oxide/data has expired, it grants a configurable item via ItemManager.CreateByName and GiveItem, then records the current unix time. Team members are also greeted count if they are awake. A short timer.Once is used only to let the client finish its initial network update before the chat line is sent, avoiding a message that can be missed during the wake transition. The cooldown map is saved on unload.

Common use cases

  • Reward players for returning

    Grant a small item or currency the first time a player wakes each real-time day, tracked with a timestamp per user ID.

  • Re-apply status effects

    Re-add custom modifiers, vanish state or UI overlays that are wiped when a player sleeps, so they persist across logouts.

  • Send server info on wake

    Print the current wipe countdown, active event or rules reminder once the player is back in control of their character.

Pitfalls

  • Not a spawn hook

    This only fires when an existing body wakes. Fresh spawns and respawns after death run other paths, so pair it with a spawn hook if you need full coverage.

  • Client may still be loading

    Chat and CUI sent immediately can be missed while the client finishes the wake transition. A one-second timer is usually enough.

  • Sleeping bag wake spam

    Waking is frequent on active servers, so keep the handler cheap and never log or print warnings inside it.

Plugin recipes that use OnPlayerSleepEnded

Build a plugin with OnPlayerSleepEnded

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

Prompt: Reward players for returning using the OnPlayerSleepEnded 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 OnPlayerSleepEnded

Generate