OnBedMade
OnBedMade is called after a player assigns themselves to a sleeping bag by running the bag's make-bed action, once the ownership record has been written. It is a notification hook: the call site ignores any return value.
void OnBedMade(SleepingBag sleepingBag, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
sleepingBag | SleepingBag | The SleepingBag component whose bed-assignment RPC just completed. Use it for its world position, net.ID, skinID and owner record; the assigning player has already been written into the bag's user data at this point. |
player | BasePlayer | The BasePlayer who was assigned as the bag's new owner by the make-bed action. This is the player whose respawn point now points at the bag, and it may be null in edge cases, so guard before using it. |
Return value
The call site ignores return values entirely (SleepingBag.RPC_MakeBed returns void and the hook is invoked as a statement). Return nothing, or return a value; neither changes whether the player becomes the bed's owner.
How it works
The hook fires at the end of SleepingBag.RPC_MakeBed, the server-side RPC a client sends when it makes a bed its respawn point. By the time Oxide reaches the call, the game has already run AssignToUser(msg.player.userID) on the bag, so the ownership change is complete and the player is the new owner.
Because the injection is the last statement of the method, there is nothing left to inspect or cancel upstream: the hook tells you that the event happened, it does not let you block it. Use player as the actor and sleepingBag for the target location, for example to announce the event in chat, apply a cooldown cost, tag the bag with a custom name, or record it in data for later use.
The method returns void, so returning a value from your hook has no effect on the game. Declaring player as BasePlayer is already the most specific useful type; declaring the bag parameter more narrowly is not possible since it is a concrete SleepingBag. There is no corresponding OnBedUnmake in vanilla; removal is covered by OnSleepingBagDestroy.
Example plugin: Broadcast bed assignments and apply a cooldown
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Bed Made Notifier", "RustPluginGenerator", "1.0.0")]
[Description("Announces sleeping bag assignments and rate-limits them per player")]
public class BedMadeNotifier : RustPlugin
{
private const string DataFile = "BedMadeNotifier";
private PluginConfig config;
private Dictionary<string, double> lastMade = new Dictionary<string, double>();
private class PluginConfig
{
[JsonProperty("Broadcast to server")]
public bool Broadcast { get; set; } = true;
[JsonProperty("Cooldown between messages (seconds)")]
public double Cooldown { get; set; } = 30.0;
}
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>
{
["Assigned"] = "Respawn point set at {0}.",
["Broadcast"] = "{0} claimed a sleeping bag.",
["Cooldown"] = "You can only set a new bed every {0} seconds."
}, this);
}
private string Msg(string key, string userId = null, params object[] args)
=> string.Format(lang.GetMessage(key, this, userId), args);
private void OnServerInitialized()
{
lastMade = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, double>>(DataFile)
?? new Dictionary<string, double>();
}
private void OnBedMade(SleepingBag sleepingBag, BasePlayer player)
{
if (sleepingBag == null || player == null || player.IsNpc || !player.IsConnected) return;
double now = Facepunch.Math.Epoch.Current;
double previous;
if (lastMade.TryGetValue(player.UserIDString, out previous) && now - previous < config.Cooldown)
{
player.ChatMessage(Msg("Cooldown", player.UserIDString, config.Cooldown));
return;
}
lastMade[player.UserIDString] = now;
Vector3 pos = sleepingBag.transform.position;
string where = string.Format("{0:0}, {1:0}", pos.x, pos.z);
player.ChatMessage(Msg("Assigned", player.UserIDString, where));
if (config.Broadcast)
Server.Broadcast(Msg("Broadcast", null, player.displayName));
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(DataFile, lastMade);
}
}
}The plugin reacts to every bed assignment. When OnBedMade fires it first rejects NPC or disconnected players, then looks up the player's last assignment timestamp in a small data dictionary keyed by UserIDString. If the previous entry is newer than the configured cooldown it sends a chat warning and returns without further action. Otherwise it records the new timestamp, saves the data, formats a localised message with the player name and the bag position, sends it to the acting player via lang messages and broadcasts it to the server. Config exposes whether broadcasting is enabled and the cooldown length; the data file lives in oxide/data and Unload flushes it so timestamps survive restarts.
Common use cases
Announce respawn-point changes
Broadcast to the server when a player claims a bag so teammates and admins know where respawns are being set, using the bag's world position from
sleepingBag.transform.position.Charge for bed making
Hook into an economy plugin and withdraw a small fee from the player each time a new bed assignment is made, skipping the charge when the player is re-claiming the same bag.
Track spawn locations
Append the player ID, bag net ID and position to an Oxide data file so staff can later review where players are setting respawns across the map.
Pitfalls
The hook cannot cancel the assignment
The ownership write happens before the hook call, and the method is void, so returning a value or throwing does nothing useful. If you need to prevent assignment, do it at the client or with a different mechanism.
Null player on edge cases
msg.playeris not guaranteed to be a valid player object in every path, so always testplayer == null || player.IsNpc || !player.IsConnectedbefore usingUserIDStringorChatMessage.Frequent calls can spam chat
Players re-click bags often while moving base. Without a per-player throttle your messages will flood chat; store a timestamp and compare against a configurable cooldown.
Build a plugin with OnBedMade
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 OnBedMade
Generate