Skip to content
RustPluginGenerator

OnRfFrequencyChange

OnRfFrequencyChange is called when a player sets a new frequency on an RF entity (broadcaster, receiver, detonator or pager). Returning a non-null value cancels the change before it is applied.

Signature
object OnRfFrequencyChange(RFBroadcaster rFBroadcaster, int num, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
rFBroadcasterRFBroadcasterThe RF entity whose frequency is being changed: an RFBroadcaster, RFReceiver, Detonator or PagerEntity depending on which ServerSetFrequency call fired the hook.
numintThe new frequency the player requested, already clamped to the valid RF range by the game before the hook runs.
playerBasePlayerThe player who triggered the change. Null for paths where the game does not pass a player, so always check before use.

Return value

Returning null lets the change continue: the entity sets the new frequency and OnRfFrequencyChanged fires afterwards. Returning any non-null value stops the original code path, so the frequency is not applied and no OnRfFrequencyChanged call happens.

How it works

The hook fires from ServerSetFrequency on RFBroadcaster, RFReceiver, Detonator and PagerEntity, right after the game clamps the requested frequency into the legal RF band. It runs for the player-driven paths: a broadcaster's frequency is set from its RPC after the reserved-frequency check passes; a receiver only reaches the hook when the sending player is valid and CanBuild() is true; a detonator reaches it after RFManager.ReserveErrorPrint has already rejected reserved numbers. Because the same hook name is used for all four types, you can declare RFBroadcaster, RFReceiver, Detonator or PagerEntity as the first parameter to narrow it to one entity type, or use BaseEntity to catch all of them. Oxide checks that each argument matches your declared parameter type before calling. The num argument is the post-clamp frequency, so it is already within range. This hook fires before the frequency is stored, making it the place to enforce rules about which numbers players may use.

Other signatures

Oxide also calls OnRfFrequencyChange from other places in the game with these parameter types. Declare the overload you need, or several:

  • object OnRfFrequencyChange(RFReceiver rFReceiver, int num, BasePlayer player)
  • object OnRfFrequencyChange(Detonator detonator, int freq, BasePlayer player)
  • object OnRfFrequencyChange(PagerEntity pagerEntity, int num, BasePlayer player)

Example plugin: Reserve a frequency range for staff

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

namespace Oxide.Plugins
{
    [Info("RfFrequencyGuard", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks players from tuning RF entities to protected frequencies unless permitted.")]
    public class RfFrequencyGuard : RustPlugin
    {
        private const string PermBypass = "rffrequencyguard.bypass";

        private PluginConfig config;

        public class PluginConfig
        {
            [JsonProperty("Protected frequency ranges (min / max)")]
            public List<Range> ProtectedRanges = new List<Range>
            {
                new Range { Min = 9000, Max = 9100 }
            };

            [JsonProperty("Notify player when change is blocked")]
            public bool NotifyPlayer = true;
        }

        public class Range
        {
            [JsonProperty("Min")]
            public int Min;

            [JsonProperty("Max")]
            public int Max;
        }

        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>
            {
                ["Blocked"] = "The frequency {0} is reserved and cannot be set by players.",
                ["NoRanges"] = "No protected frequency ranges are configured."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
        {
            return string.Format(lang.GetMessage(key, this, userId), args);
        }

        private void Init()
        {
            permission.RegisterPermission(PermBypass, this);
            if (config.ProtectedRanges == null || config.ProtectedRanges.Count == 0)
                PrintWarning(Msg("NoRanges"));
        }

        private object OnRfFrequencyChange(BaseEntity entity, int frequency, BasePlayer player)
        {
            if (entity == null) return null;
            if (player == null) return null;
            if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;

            foreach (Range range in config.ProtectedRanges)
            {
                if (range == null) continue;
                if (frequency < range.Min || frequency > range.Max) continue;

                if (config.NotifyPlayer)
                    player.ChatMessage(Msg("Blocked", player.UserIDString, frequency));
                return false;
            }

            return null;
        }
    }
}

The plugin keeps a configurable list of protected frequency ranges and a permission that grants access to them. When a player changes the frequency on any RF entity, OnRfFrequencyChange checks the requested number against the ranges. If it falls inside a protected range and the player lacks the bypass permission, the hook sends a chat message and returns a non-null object, which cancels the change. Allowed changes return null so the game applies the frequency normally and fires OnRfFrequencyChanged. The config ships with a default protected range so the plugin works out of the box, and the message text lives in the language file.

Common use cases

  • Staff-only frequency bands

    Block regular players from setting frequencies reserved for admins or event organizers by returning non-null when the number is in a protected range.

  • Whitelist of allowed channels

    Only permit a fixed set of frequencies (for example team channels on a roleplay server) and cancel every other request.

  • Anti-grief frequency changes

    Stop players from retuning receivers during a raid by checking team membership or build authorization before letting the change through.

Pitfalls

  • Player can be null

    The player argument is not guaranteed to be set on every path. Check it before calling permission checks or sending messages, or your hook will throw.

  • Fire-and-forget cancellation

    Returning non-null silently drops the change from the game's perspective; send your own feedback to the player or they will just see the frequency stay the same.

  • Entity type narrowing

    Declaring RFBroadcaster only catches broadcasters. To cover receivers, detonators and pagers, declare BaseEntity or add separate hook methods with the specific types.

Build a plugin with OnRfFrequencyChange

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

Prompt: Staff-only frequency bands using the OnRfFrequencyChange 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 OnRfFrequencyChange

Generate