OnRfBroadcasterRemove
OnRfBroadcasterRemove is called when a broadcaster is about to be unregistered from an RF frequency, before RFManager actually drops it from the broadcaster set. Returning a non-null value cancels the removal.
object OnRfBroadcasterRemove(IRFObject obj, int frequency)Parameters
| Parameter | Type | Description |
|---|---|---|
obj | IRFObject | The RF broadcaster object being removed from the frequency. It is an IRFObject, not a BaseEntity, so cast it to the concrete entity type (for example BaseEntity or IOEntity) when you need position or ownership. |
frequency | int | The RF frequency the broadcaster is being unregistered from, already clamped by RFManager before the hook fires. |
Return value
Returning null (or any value when your method returns void) lets the removal continue as normal. Returning a non-null value stops RFManager.RemoveBroadcaster early, and since the original method returns void, the broadcaster stays attached to that frequency.
How it works
RFManager.RemoveBroadcaster(int frequency, IRFObject obj) runs whenever an entity that broadcasts on RF is taken off the air: a dead or destroyed RF broadcaster, an unpowered/deactivated device, or anything game code does that calls this method. Oxide invokes OnRfBroadcasterRemove after clamping the frequency and before it touches the broadcaster set, so the hook sees the object while it is still registered.
obj is the IRFObject being removed. It is often a BaseEntity (RF receiver, broadcast-capable deployable, spawned transmitter), but the parameter is the interface, so cast defensively with as and null-check before using entity members. frequency is the already-clamped integer frequency, useful for frequency-keyed bookkeeping such as tracking which transmitters were live.
You cannot narrow this hook by declaring a more specific first parameter: Oxide only calls your method when the argument is an instance of the declared type, and objects that are not entities would silently be skipped. Keep IRFObject and cast inside. The hook also fires as part of entity cleanup, so keep it cheap and avoid logging.
Example plugin: Keep a killswitch transmitter broadcasting
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Rf Broadcaster Keeper", "RustPluginGenerator", "1.0.0")]
[Description("Prevents broadcasters on a configured RF frequency from being removed")]
public class RfBroadcasterKeeper : RustPlugin
{
private const string PermAdmin = "rfbroadcasterkeeper.admin";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Protected frequency (0 disables protection)")]
public int ProtectedFrequency = 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);
private void Init()
{
permission.RegisterPermission(PermAdmin, this);
}
private object OnRfBroadcasterRemove(IRFObject obj, int frequency)
{
if (config.ProtectedFrequency == 0 || frequency != config.ProtectedFrequency) return null;
var entity = obj as BaseEntity;
if (entity == null || entity.IsDestroyed) return null;
return true;
}
[ConsoleCommand("rfkeeper.set")]
private void CmdSet(ConsoleSystem.Arg arg)
{
if (!arg.IsAdmin) return;
int frequency = arg.GetInt(0, 0);
if (frequency <= 0)
{
arg.ReplyWith("Usage: rfkeeper.set <frequency>");
return;
}
config.ProtectedFrequency = frequency;
SaveConfig();
arg.ReplyWith($"RF frequency {frequency} is now protected from broadcaster removal");
}
[ConsoleCommand("rfkeeper.clear")]
private void CmdClear(ConsoleSystem.Arg arg)
{
if (!arg.IsAdmin) return;
config.ProtectedFrequency = 0;
SaveConfig();
arg.ReplyWith("RF broadcaster protection disabled");
}
[ChatCommand("rfkeeper")]
private void CmdChat(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
{
player.ChatMessage("You do not have permission to use this command.");
return;
}
player.ChatMessage(config.ProtectedFrequency == 0
? "No RF frequency is currently protected."
: $"RF frequency {config.ProtectedFrequency} is protected from broadcaster removal.");
}
}
}The plugin lets an admin mark one RF frequency as protected. Whenever RFManager tries to remove any broadcaster from that frequency, OnRfBroadcasterRemove checks the stored frequency and returns a non-null value, which halts the removal and keeps the transmitter on the air. rfkeeper.set <frequency> and rfkeeper.clear are console commands that persist the setting through the plugin config. The hook only compares an integer and reads a cached field, so it stays cheap even when many entities are being removed during a restart of the map's RF network.
Common use cases
Protected command frequencies
Pin a transmitter on a staff or trap frequency so map cleanup, device destruction or power loss cannot silently remove the broadcaster.
Audit trail for RF networks
Track which frequencies lose broadcasters over a session to find deployables that stop transmitting; store the counts in oxide/data instead of printing from the hook.
Conditional removal ban
Allow removal only for objects owned by staff or inside a given zone, and cancel it for everything else that uses the protected frequency.
Pitfalls
Cancelling removal leaks stale objects
If the broadcaster is being removed because the entity is dead or destroyed, keeping it registered leaves a dead reference in the RF manager. Only cancel when you are certain the object is still usable.
IRFObject is not a BaseEntity
The parameter type is the interface. Cast with
asand null-check; reading transform or OwnerID directly will not compile and casting blindly can fail.Frequency is clamped
The value passed to the hook is already passed through RFManager.ClampFrequency, so out-of-range values never reach you. Do not compare against an unclamped number you stored elsewhere.
Build a plugin with OnRfBroadcasterRemove
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 OnRfBroadcasterRemove
Generate