OnIORefCleared
OnIORefCleared is called after an IOEntity.IORef releases its link to another IOEntity. It fires inside IORef.Clear, once the internal entity reference has already been set to null.
void OnIORefCleared(IOEntity.IORef iORef, IOEntity obj)Parameters
| Parameter | Type | Description |
|---|---|---|
iORef | IOEntity.IORef | The IOEntity.IORef handle being cleared. Its entity reference has already been released when your hook runs; available if you need to compare it against references you stored earlier. |
obj | IOEntity | The IOEntity that the reference pointed to before it was cleared (the game captured ioEnt first, then nulled it), or null if the reference was already empty. This is the entity you inspect or act on. |
Return value
The hook sits on a void method and the return value is ignored, so returning null or any value has no effect on IORef.Clear. The reference is cleared regardless of what the hook does.
How it works
The hook fires from IOEntity.IORef.Clear, which is used when an IO entity's input or output reference is dissolved, for example when a wire connection is cut or a referenced entity is disconnected from a circuit. The game captures the old ioEnt into a local variable, sets the field to null, clears the entity reference and only then calls the hook, so by the time your code runs the reference is already empty.
iORef is the reference object itself; it no longer points anywhere, so treat it as an identifier rather than a live link. obj is the IOEntity that was previously linked and is usually the useful parameter: use it to inspect the entity that just left the circuit, such as a power source, a switch or a button. Either parameter can be null in edge cases, so null-check both.
This is a fire-and-forget notification: firing it does not change the clear operation. Because wire edits and entity teardown can produce many clears at once, do not print to console from this hook; batch or debounce any bookkeeping. The hook also fires during server shutdown and entity kill, when the old target may already be destroyed.
Example plugin: Track when player-owned IO entities have a reference cleared
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("IORef History", "RustPluginGenerator", "1.0.0")]
[Description("Records recent IO reference clears on player-owned entities for admin review")]
public class IORefHistory : RustPlugin
{
private const string PermUse = "iorefhistory.admin";
private PluginConfig config;
private readonly List<string> history = new List<string>();
private class PluginConfig
{
[JsonProperty("Maximum entries kept in memory")]
public int MaxEntries = 50;
}
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>
{
["NoHistory"] = "No IO reference clears have been recorded yet.",
["Header"] = "{0} recent IO reference clears:",
["Entry"] = "{0}. {1} (owner {2})",
["NoPermission"] = "You do not have permission to use this command."
}, 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 void OnIORefCleared(IOEntity.IORef iORef, IOEntity obj)
{
if (obj == null || obj.IsDestroyed)
return;
var owner = BasePlayer.FindByID(obj.OwnerID);
if (owner == null || !owner.IsConnected)
return;
string entry = Msg("Entry", null, 0, obj.ShortPrefabName, owner.displayName);
entry = entry.Substring(entry.IndexOf('.') + 1);
history.Add(entry);
while (history.Count > Math.Max(1, config.MaxEntries))
history.RemoveAt(0);
}
[ChatCommand("iorefhistory")]
private void CmdHistory(BasePlayer player, string command, string[] args)
{
if (player == null)
return;
if (!permission.UserHasPermission(player.UserIDString, PermUse))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return;
}
if (history.Count == 0)
{
player.ChatMessage(Msg("NoHistory", player.UserIDString));
return;
}
player.ChatMessage(Msg("Header", player.UserIDString, history.Count));
for (int i = 0; i < history.Count && i < 10; i++)
player.ChatMessage(Msg("Entry", player.UserIDString, i + 1, history[i], ""));
}
private void Unload()
{
history.Clear();
}
}
}The plugin records every OnIORefCleared call where the cleared entity exists, is not destroyed, and its owner is an online player found by obj.OwnerID. Each history entry is stored as the entity's short prefab name followed by the owner's display name, in a bounded in-memory list; when the list exceeds MaxEntries (config key Maximum entries kept in memory, default 50, clamped to at least 1) the oldest entry is removed. Admins with the iorefhistory.admin permission can run /iorefhistory to see the most recent entries in chat; only the first 10 retained entries are printed. The hook returns early when obj is null or destroyed, or when no connected owner is found, which keeps it safe during shutdown. The history list is cleared on plugin unload. An invalid config file produces a warning and falls back to defaults.
Common use cases
Audit wire tampering
Record which player-owned entities lose IO references so staff can investigate suspicious rewiring of power circuits or traps on a build server.
Circuit bookkeeping for custom logic
If your plugin tracks connected power networks by keeping its own map of links, prune entries when the hook reports that a reference was cleared.
Debug electrical plugins
Collect a short in-memory trail of cleared references and expose it through a chat command instead of spamming the console during edits.
Pitfalls
The reference is already gone
When the hook runs,
IORefno longer points at anything. Read the target from the second parameter and do not expectiORefto resolve to an entity.Fires in bursts and during shutdown
Removing a large electrical build or stopping the server produces many calls in a row. Avoid console output and heavy per-call work, and null-check the entity and its owner everywhere.
Not the same as a wire being cut
The hook reports that a reference was cleared, not the player action or item change that caused it. Use input hooks or entity hooks if you need the initiating player.
Build a plugin with OnIORefCleared
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 OnIORefCleared
Generate