Skip to content
RustPluginGenerator

OnPlayerSpectate

OnPlayerSpectate is called from BasePlayer.StartSpectating, before the player is flagged as a spectator and their layer is switched. Returning a non-null value cancels that transition.

Signature
object OnPlayerSpectate(BasePlayer player, string spectateFilter)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer who is about to enter spectator mode. Use it to check permissions, team membership or current state before deciding whether to allow spectating.
spectateFilterstringThe spectator filter string currently set on the player. It reflects the game's spectate filter field at the moment StartSpectating runs.

Return value

Returning null lets the game continue: the player is flagged as spectating, moved to the spectator layer, and sent the "Becoming Spectator" message. Returning any non-null value (a common choice is true or false) prevents the transition from happening.

How it works

This hook fires inside BasePlayer.StartSpectating, which Rust invokes when a player is switched into spectator mode (the classic admin/F1 spectate flow, including /spectate style commands and admin tools that call it). At that point the player is not yet flagged PlayerFlags.Spectating, their GameObject layer has not been changed to the spectator layer, and the "Becoming Spectator" chat line has not been sent. The player parameter is the one entering spectate mode; spectateFilter carries whatever filter string is currently set, useful if you only want to gate certain filter states.

Returning a non-null value stops the original body from running, so the player stays a normal player. The hook only fires for real players, so narrowing the parameter type buys nothing. Use it to enforce spectator policy: block spectating for non-staff, cancel spectating during a PvP window, or notify your own systems that a player is about to go invisible to other players.

Example plugin: Restrict spectator mode to staff groups

SpectateGuard.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Spectate Guard", "RustPluginGenerator", "1.0.0")]
    [Description("Restricts who may enter spectator mode and warns staff when someone spectates.")]
    public class SpectateGuard : RustPlugin
    {
        private const string PermSpectate = "spectateguard.spectate";

        private PluginConfig config;

        public class PluginConfig
        {
            [JsonProperty("Allowed group names (besides users with the permission)")]
            public List<string> AllowedGroups = new List<string> { "admin", "moderator" };

            [JsonProperty("Broadcast to admins when a player starts spectating")]
            public bool NotifyAdmins = 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>
            {
                ["NotAllowed"] = "You are not allowed to enter spectator mode.",
                ["AdminNotice"] = "{0} ({1}) started spectating."
            }, 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(PermSpectate, this);
        }

        private bool IsAllowed(BasePlayer player)
        {
            if (player.IsAdmin) return true;
            if (permission.UserHasPermission(player.UserIDString, PermSpectate)) return true;

            foreach (string group in config.AllowedGroups)
            {
                if (permission.UserHasGroup(player.UserIDString, group)) return true;
            }
            return false;
        }

        private object OnPlayerSpectate(BasePlayer player, string spectateFilter)
        {
            if (player == null) return null;

            if (!IsAllowed(player))
            {
                player.ChatMessage(Msg("NotAllowed", player.UserIDString));
                return false;
            }

            if (config.NotifyAdmins)
            {
                string notice = Msg("AdminNotice", null, player.displayName, player.UserIDString);
                foreach (BasePlayer target in BasePlayer.activePlayerList)
                {
                    if (target != null && target.IsAdmin)
                        target.ChatMessage(notice);
                }
            }

            return null;
        }
    }
}

SpectateGuard hooks OnPlayerSpectate and checks three things in order: the player is an admin, the player holds spectateguard.spectate, or the player belongs to one of the groups listed in the config (admin, moderator by default). If none match, the plugin sends a localized chat message and returns false, which cancels the original StartSpectating body so the player stays in normal play. When the player is allowed, it optionally notifies every online admin with the spectator's name and ID, then returns null so Rust performs the normal spectator transition. The permission is registered in Init, and the config can be reloaded to adjust the allowed group list without recompiling.

Common use cases

  • Staff-only spectating

    Block regular players from entering spectator mode on a PvE or competitive server where going invisible would be an exploit. Admins and holders of a permission stay free to spectate.

  • Audit trail for spectators

    Send a chat notice or log entry whenever a staff member starts spectating, so other admins can see who is watching which area and when.

  • Disable spectating during events

    Temporarily return a non-null value for everyone while a PvP event is running, then restore normal behavior when the event ends.

Pitfalls

  • PlayerFlags.Spectating is not set yet

    Inside the hook the player is still a regular active player. Do not call IsSpectating() or rely on spectator-only state; it will not reflect the transition you are intercepting.

  • Cancelling leaves the player where they were

    Returning a non-null value exits before the layer change and the chat message, so the client gets no feedback from the game itself. Send your own message if the player should know why spectating was refused.

  • Group checks need the permission system loaded

    permission.UserHasGroup works once the Oxide permission system is initialized. Register any plugin permission in Init so group and user grants resolve correctly on the first spectate attempt.

Build a plugin with OnPlayerSpectate

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

Prompt: Staff-only spectating using the OnPlayerSpectate 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 OnPlayerSpectate

Generate