Skip to content
RustPluginGenerator

OnBuildingSplit

OnBuildingSplit is called by ServerBuildingManager.Split each time the server carves a detached group of building blocks out of a building into a new building ID. It fires once per new building created during the split.

Signature
void OnBuildingSplit(BuildingManager.Building oldBuilding, uint newBuildingId)

Parameters

Hook parameters
ParameterTypeDescription
oldBuildingBuildingManager.BuildingThe BuildingManager.Building that is being torn apart by the split. It still holds the blocks that remain to be processed, so its buildingBlocks list shrinks as the split loop advances.
newBuildingIduintThe freshly allocated building ID that the next set of connected blocks will be attached to. You can read it for logging or bookkeeping, but you cannot change it from this hook.

Return value

The return value is ignored: the patcher continues the original method no matter what the hook returns, and Split still returns void. Returning anything has no effect on building IDs or block ownership.

How it works

The hook fires inside ServerBuildingManager.Split, which runs when a building loses blocks and the remaining pieces are no longer all connected. The server takes the first block of the old building, allocates a new building ID, fires OnBuildingSplit with the old BuildingManager.Building object and that new ID, then attaches every block reachable from the first one to the new ID. The loop repeats while the old building still has blocks, so a single break can produce several calls.

oldBuilding gives you the pre-split building object: you can read its ID, inspect buildingBlocks, and walk GetBuildingPrivilege(). newBuildingId is the identifier the next chunk will get, useful for correlating your own records with the engine's IDs. There is no return value you can use to cancel or alter the split; the hook is observational.

The hook only fires for structural recalculation, so it complements placement and upgrade hooks rather than replacing them. Keep handlers cheap because splits happen immediately after block destruction, often during raids when many blocks die in a short window.

Example plugin: Log building splits to chat for admins

BuildingSplitNotifier.cs
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Building Split Notifier", "RustPluginGenerator", "1.0.0")]
    [Description("Notifies online admins when the server splits a building into new building IDs")]
    public class BuildingSplitNotifier : RustPlugin
    {
        private const string PermNotify = "buildingsplitnotifier.notify";

        private PluginConfig config;
        private readonly List<string> pendingMessages = new List<string>();
        private Timer flushTimer;

        private class PluginConfig
        {
            [JsonProperty("Minimum seconds between notifications")]
            public float ThrottleSeconds = 3f;

            [JsonProperty("Include block count in message")]
            public bool ShowBlockCount = 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>
            {
                ["Split"] = "Building {0} split into new building {1} ({2} blocks left).",
                ["SplitShort"] = "Building {0} split into new building {1}."
            }, 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(PermNotify, this);
        }

        private void OnBuildingSplit(BuildingManager.Building oldBuilding, uint newBuildingId)
        {
            if (oldBuilding == null) return;

            string message = config.ShowBlockCount
                ? Msg("Split", null, oldBuilding.ID, newBuildingId, oldBuilding.buildingBlocks?.Count ?? 0)
                : Msg("SplitShort", null, oldBuilding.ID, newBuildingId);

            pendingMessages.Add(message);
            if (pendingMessages.Count > 20) pendingMessages.RemoveAt(0);
        }

        private void OnServerInitialized()
        {
            flushTimer?.Destroy();
            flushTimer = timer.Every(Math.Max(1f, config.ThrottleSeconds), FlushMessages);
        }

        private void FlushMessages()
        {
            if (pendingMessages.Count == 0) return;

            List<string> batch = new List<string>(pendingMessages);
            pendingMessages.Clear();

            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected) continue;
                if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, PermNotify)) continue;

                foreach (string line in batch)
                {
                    player.ChatMessage(line);
                }
            }
        }

        private void Unload()
        {
            flushTimer?.Destroy();
            flushTimer = null;
            pendingMessages.Clear();
        }
    }
}

The plugin registers a permission and notifies online admins whenever the server splits a building. It stores the new building ID together with a timestamp in a small in-memory queue cleared by a repeating timer, so raids that split many buildings in a burst do not flood chat. Each notification tells the admin how many blocks the old building still holds at the moment of the call, which hints at how much of the structure is being reassigned. Messages go through the language file, and the permission prefix matches the lowercase class name so server owners can grant it with oxide.grant.

Common use cases

  • Raid diagnostics for staff

    Tell admins when a base's connectivity breaks apart so they can watch for suspicious building patterns during reports.

  • Correlating building IDs in your own data

    Record the new building ID alongside the old one when you persist structure data, so later saves can still match blocks to their original group.

  • Metrics on base integrity

    Count splits per hour to see how often large compounds are being breached, then feed the numbers into a status command.

Pitfalls

  • It can fire several times per break

    The split loop runs until the old building has no blocks left, so one collapsed section can trigger multiple calls with different new IDs. Aggregate or throttle instead of sending one message per call.

  • The new building may not exist yet

    The building with newBuildingId is looked up after the hook returns, so calling BuildingManager.server.GetBuilding(newBuildingId) inside the hook can return null. Do not rely on the entity side being in place.

  • No cancellation

    The hook return value is ignored, so you cannot veto a split or merge it back. Use OnBuildingMerge for the opposite path and keep this hook observational.

Build a plugin with OnBuildingSplit

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

Prompt: Raid diagnostics for staff using the OnBuildingSplit 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 OnBuildingSplit

Generate