OnEntityStabilityCheck
OnEntityStabilityCheck is called at the start of StabilityEntity.StabilityCheck, before the game evaluates whether the entity's current stability is valid. Returning a non-null value skips the original stability check for that entity.
object OnEntityStabilityCheck(StabilityEntity stabilityEntity)Parameters
| Parameter | Type | Description |
|---|---|---|
stabilityEntity | StabilityEntity | The StabilityEntity (BuildingBlock, and other entities that carry stability) whose stability is being validated. It is the entity instance passed to StabilityCheck, so you can inspect its grade, position, building privilege, health and owners. |
Return value
Return null (or nothing) to let the game run its normal stability check on the entity. Return any non-null object to skip the original StabilityEntity.StabilityCheck body for that call, so the entity is not re-evaluated this pass.
How it works
StabilityCheck runs on a StabilityEntity when the server validates its support graph, for example after a building block is placed or destroyed nearby. Oxide fires OnEntityStabilityCheck first, passing the entity, so you can veto that pass. Because the hook fires at the top of the method, a non-null return short-circuits the rest of StabilityCheck and the entity keeps whatever stability it currently holds for this tick; the original method returns void, so the returned object is not used as a value, it only signals that the vanilla routine should be skipped.
Use the parameter to inspect what you care about: stabilityEntity.grade, stabilityEntity.buildingID, stabilityEntity.GetBuildingPrivilege(), stabilityEntity.OwnerID or stabilityEntity.ShortPrefabName. Declaring a more specific parameter type than StabilityEntity narrows dispatch to those entities only; for other types Oxide skips your method. Keep the method fast and never log inside it, since stability checks run frequently on large bases.
Example plugin: Protect bases owned by a whitelisted group from stability checks
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Stability Shield", "RustPluginGenerator", "1.0.0")]
[Description("Skips building stability checks for bases owned by whitelisted players while protection is enabled.")]
public class StabilityShield : RustPlugin
{
private const string PermAdmin = "stabilityshield.admin";
private PluginConfig config;
private bool protectionActive;
private static readonly object SkipMarker = new object();
private class PluginConfig
{
[JsonProperty("Enable protection on load")]
public bool EnabledOnLoad { get; set; } = true;
[JsonProperty("Whitelisted Steam IDs (cupboard owner)")]
public List<string> WhitelistedOwners { get; set; } = new List<string>();
}
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>
{
["NoPermission"] = "You do not have permission to use this command.",
["Enabled"] = "Stability protection is now ON for {0} whitelisted owners.",
["Disabled"] = "Stability protection is now OFF."
}, 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(PermAdmin, this);
}
private void OnServerInitialized()
{
protectionActive = config.EnabledOnLoad;
}
[ChatCommand("stability")]
private void CmdStability(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, PermAdmin))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return;
}
protectionActive = !protectionActive;
player.ChatMessage(protectionActive
? Msg("Enabled", player.UserIDString, config.WhitelistedOwners.Count)
: Msg("Disabled", player.UserIDString));
}
private object OnEntityStabilityCheck(StabilityEntity stabilityEntity)
{
if (!protectionActive || stabilityEntity == null) return null;
var privilege = stabilityEntity.GetBuildingPrivilege();
if (privilege == null || privilege.OwnerID == 0UL) return null;
if (!config.WhitelistedOwners.Contains(privilege.OwnerID.ToString())) return null;
return SkipMarker;
}
}
}The plugin lets an admin toggle a protection mode with a chat command. While enabled, OnEntityStabilityCheck inspects the entity's building privilege; if the cupboard owner's Steam ID is in the configured whitelist, the hook returns a non-null marker so the vanilla stability check is skipped and a collapsing player-built base will not immediately validate away its unstable pieces. Configuration holds the whitelist of Steam IDs and a default on/off switch. All hook parameters are null-checked, no chat output happens inside the hook, and the message shown to the player comes from the language file.
Common use cases
Hold unstable structures during a raid event
Return a non-null value for blocks on a whitelisted building while a scheduled event is active, so a base does not instantly collapse from a single support loss during the event window.
Grandfather legacy bases
Skip stability re-validation for entities whose buildingID belongs to a server-owned whitelist, giving admins a way to keep landmark structures standing after a map change.
Gate checks for a specific grade
Inspect
stabilityEntity.gradeto only short-circuit Twigs or Wood, letting higher-tier building blocks still be validated normally.
Pitfalls
Silent physics drift
Skipping the check does not make an entity stable; it only skips validation. Blocks that are already unsupported can remain standing until another check or a server restart, which may look like ghost structures to players.
Frequent calls on large bases
StabilityCheck runs for many building blocks after construction changes, so do not iterate all entities, run LINQ or log here. Read only the fields you need and return quickly.
Return value is not a fix
The original method returns void, so the returned object is only a signal to skip the routine. Returning true or a custom object has the same effect; do not expect to be able to change the compiled stability value this way.
Build a plugin with OnEntityStabilityCheck
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 OnEntityStabilityCheck
Generate