OnDemoRecordingStart
OnDemoRecordingStart is called on the server right before BasePlayer.StartServerDemoRecording begins writing a demo file for a player. Returning a non-null value stops the recording from starting.
object OnDemoRecordingStart(string text, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
text | string | The relative file path the server intends to write the demo to, formatted as demos/<steamid>/<yyyy-MM-dd-hhmmss>.dem. Read it to log or inspect where the recording would be stored. |
player | BasePlayer | The BasePlayer whose connection is about to start recording. Use it to check permissions, identity or connection state. |
Return value
Return null (or nothing) to let the game continue and start the recording exactly as usual. Return any non-null value to stop the original path: the start log line, the StartRecording call and everything after it are skipped, so no demo is recorded.
How it works
The hook fires inside BasePlayer.StartServerDemoRecording, after the method has confirmed the player has a live network connection that is not already recording, and after it has built the target path demos/<UserIDString>/<timestamp>.dem. It fires just before the game logs the start message and calls the connection's recording start routine, so at this point nothing has been written to disk. text is the relative demo path; player is the BasePlayer being recorded. The hook only runs on the server when that method is invoked, which normally happens when an admin starts a server-side demo of a player. Declaring player as BasePlayer is the only supported type here; a broader base type would not narrow anything useful because the injection always passes the owning player. Use it to gate demo recording by permission, to log who gets recorded and where, or to warn players. Returning null lets the vanilla recording proceed unchanged.
Example plugin: Restrict server demo recording to a permission
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Demo Recording Guard", "RustPluginGenerator", "1.0.0")]
[Description("Restricts server demo recording to a permission and logs every attempt")]
public class DemoRecordingGuard : RustPlugin
{
private const string PermUse = "demorecordingguard.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Log allowed recordings")]
public bool LogAllowed { get; set; } = true;
[JsonProperty("Deny everyone without permission")]
public bool DenyWithoutPermission { get; set; } = 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>
{
["Denied"] = "You are not allowed to record demos on this server.",
["Recording"] = "A server demo of you is being recorded."
}, 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);
}
private object OnDemoRecordingStart(string text, BasePlayer player)
{
if (player == null) return null;
if (config.DenyWithoutPermission && !permission.UserHasPermission(player.UserIDString, PermUse))
{
Puts($"Blocked demo recording for {player.displayName} ({player.UserIDString}) target {text}");
player.ChatMessage(Msg("Denied", player.UserIDString));
return false;
}
if (config.LogAllowed)
{
Puts($"Demo recording started for {player.displayName} ({player.UserIDString}) target {text}");
player.ChatMessage(Msg("Recording", player.UserIDString));
}
return null;
}
}
}The plugin registers a demorecordingguard.use permission in Init. When OnDemoRecordingStart fires it checks the player with permission.UserHasPermission and returns a non-null value for anyone lacking it, which skips the game's StartRecording call so no file is created. Allowed recordings are logged to oxide/logs style console output through Puts (called at most once per recording attempt, which is a rare event) and the target path is included for later review. Messages are sent through the language file so admins can translate the denial notice. Config holds a toggle to log allowed starts and a flag to deny everyone except admins when the permission check is not desired.
Common use cases
Admin-only demos
Block recording for players without a specific permission so only trusted staff can be captured server-side.
Audit trail
Log the exact demo path and player id each time a recording begins so you can correlate files on disk with incidents.
Warn before capture
Send a chat notice to the player being recorded so they know a demo is starting, while still letting the vanilla recording run.
Pitfalls
Returning a value silently stops capture
Any non-null return cancels the recording with no error to the caller. Make the deny path explicit in your logs so admins do not wonder why demos are missing.
No start event when blocked
Because the return short-circuits the method, OnDemoRecordingStarted and the connection recording never happen. Do not expect a stop hook to fire for a blocked attempt.
Do not record from here
The hook runs before the path is used; writing your own demo handling here can conflict with the server. Keep logic to checks, messages and logging.
Build a plugin with OnDemoRecordingStart
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 OnDemoRecordingStart
Generate