OnDemoRecordingStarted
OnDemoRecordingStarted is called on the server after a player's demo recording has been initialized and the monitoring repeat has been scheduled, right before control returns from BasePlayer.StartServerDemoRecording. It is not a cancellation hook.
void OnDemoRecordingStarted(string text, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
text | string | The demo header text produced by the server right before recording starts, containing metadata such as the world URL and the recording timestamp. Useful if you want to inspect or match the recording session. |
player | BasePlayer | The BasePlayer whose client-side demo recording is starting. Always non-null here because the hook is called from BasePlayer.StartServerDemoRecording. |
Return value
The hook is called in a void method and the return value is ignored. Returning null or any value has no effect on the recording, so no cancellation or override is possible from this hook.
How it works
The hook fires from BasePlayer.StartServerDemoRecording, after the server has built the demo header text, sent a complete snapshot to the client, and scheduled the actionMonitorServerDemoRecording repeat at a 10 second interval. The text argument carries that header content; player is the recording player. Because the call sits at the end of the method, treat this as a notification that recording has begun, not as a gate you can use to block it.
Declaring the parameter as BasePlayer matches the actual argument type, so Oxide always dispatches the call. There is no meaningful way to narrow it further. The method returns void, so whatever your hook returns has no effect on the game code.
Practical notes: use it to log or audit who is recording, to apply rate limits, or to attach follow-up state you clean up in OnDemoRecordingStopped. It only tracks server-side initiated recordings through this method, so do not assume every client demo goes through it. Keep the body cheap; it fires per recording, not per tick.
Example plugin: Track and limit demo recordings per player
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Demo Recording Guard", "RustPluginGenerator", "1.0.0")]
[Description("Logs and caps server-side demo recordings per player")]
public class DemoRecordingGuard : RustPlugin
{
private const string PermUse = "demorecordingguard.use";
private PluginConfig config;
private readonly Dictionary<ulong, int> activeRecordings = new Dictionary<ulong, int>();
private Dictionary<string, string> recordingLog = new Dictionary<string, string>();
private class PluginConfig
{
[JsonProperty("Max active recordings per player")]
public int MaxActiveRecordings = 2;
[JsonProperty("Notify player on start")]
public bool NotifyOnStart = true;
}
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>
{
["RecordingStarted"] = "Demo recording started. Active recordings: {0}",
["LimitReached"] = "You have reached the recording limit ({0})."
}, 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(PermUse, this);
recordingLog = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, string>>(Name) ?? new Dictionary<string, string>();
}
private void OnDemoRecordingStarted(string text, BasePlayer player)
{
if (player == null) return;
int count;
activeRecordings.TryGetValue(player.userID, out count);
count++;
activeRecordings[player.userID] = count;
recordingLog[player.UserIDString] = DateTime.UtcNow.ToString("u");
Interface.Oxide.DataFileSystem.WriteObject(Name, recordingLog);
if (permission.UserHasPermission(player.UserIDString, PermUse) && config.NotifyOnStart)
player.ChatMessage(Msg("RecordingStarted", player.UserIDString, count));
if (count > config.MaxActiveRecordings)
PrintWarning($"{player.displayName} ({player.UserIDString}) started {count} concurrent demo recordings");
}
private void OnDemoRecordingStopped(string text, BasePlayer player)
{
if (player == null) return;
activeRecordings.Remove(player.userID);
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, recordingLog);
activeRecordings.Clear();
}
}
}The plugin keeps a per-player recording count in memory and logs each new recording through a configurable chat notice. When OnDemoRecordingStarted fires it checks the player's permission, increments the counter, and warns admins in console when the configured cap is exceeded. OnDemoRecordingStopped clears the player's counter and records the active flag. Data is stored with Interface.Oxide.DataFileSystem so admins keep a simple recording log across restarts, and the timer-free design means nothing needs tearing down in Unload beyond saving the log.
Common use cases
Audit who records demos
Log the player name, Steam ID and timestamp every time a server demo recording begins, so staff can correlate recordings with reports.
Enforce a per-player cap
Count active recordings per player and alert staff when someone exceeds a configured limit, which is useful on servers that allow players to record for evidence.
Grant recording-related kits or notices
Send a chat notice or apply a permission-scoped reward when a permitted player starts a recording, mirroring the same behaviour in OnDemoRecordingStopped.
Pitfalls
It cannot block recording
The hook fires after the snapshot has been sent and the monitor scheduled. Returning a value does not stop the demo, so implement any blocking logic earlier in the flow if you need it.
Not every demo passes through here
Only server-initiated recordings via BasePlayer.StartServerDemoRecording hit this hook. Client-side demo commands and third-party tools may use a different path, so do not treat the hook as an exhaustive recording log.
Expect a paired stop callback
Always pair your OnDemoRecordingStarted logic with OnDemoRecordingStopped handling so counters and UI are cleared when recording ends or the player disconnects.
Build a plugin with OnDemoRecordingStarted
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 OnDemoRecordingStarted
Generate