Skip to content
RustPluginGenerator

OnStructureRotate

OnStructureRotate is called when a player tries to rotate a placed building block (wall, floor, foundation piece) with the rotate key, right before the block's rotation is applied.

Signature
object OnStructureRotate(BuildingBlock buildingBlock, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
buildingBlockBuildingBlockThe BuildingBlock being rotated by the player's rotate input. It carries the grade, buildingID and current transform, so you can check ownership, position or privilege before deciding.
playerBasePlayerThe BasePlayer who pressed the rotate key while looking at the block. Use it for permission checks, distance checks or building privilege tests.

Return value

Returning null lets the game continue and apply the rotation. Returning anything non-null (for example true, or a string error message) cancels the rotation: the block keeps its current orientation and the surrounding entity/skin refresh is skipped.

How it works

Rust fires this hook from BuildingBlock.DoRotation after the game has already confirmed the player can interact, that the block definition allows rotation after placement (canRotateAfterPlacement) and that the player passes CanRotate. It is the last check before the server multiplies the block's local rotation by the definition's rotation amount and then refreshes entity links, surrounding entities and skin. The hook does not fire for blocks whose definition cannot rotate after placement, so many deployables never reach it.

buildingBlock is the block itself: you can read grade, buildingID, its OwnerID, the position via transform.position, or call GetBuildingPrivilege() / IsAuthed(player) through BuildingPrivlidge to gate the action. player is the one pressing the key, so permission groups, team ownership and admin bypasses are all checkable.

Because the game calls the hook with the concrete BuildingBlock and BasePlayer types, narrowing is not useful here - declare the exact types. Any non-null return cancels the rotation entirely; the block keeps its current orientation and no network refresh happens.

Example plugin: Restrict rotation of other players' structures

RotateOwnershipGuard.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Rotate Ownership Guard", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks rotation of building blocks a player neither owns nor is authorized on.")]
    public class RotateOwnershipGuard : RustPlugin
    {
        private const string PermBypass = "rotateownershipguard.bypass";

        private PluginConfig config;

        public class PluginConfig
        {
            [JsonProperty("Enable rotation guard")]
            public bool Enabled { get; set; } = true;

            [JsonProperty("Admins bypass the check")]
            public bool AdminsBypass { get; set; } = true;

            [JsonProperty("Notify player when rotation is blocked")]
            public bool NotifyPlayer { get; set; } = 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>
            {
                ["Blocked"] = "You are not allowed to rotate this structure."
            }, 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(PermBypass, this);
        }

        private object OnStructureRotate(BuildingBlock buildingBlock, BasePlayer player)
        {
            if (!config.Enabled || buildingBlock == null || player == null) return null;
            if (buildingBlock.IsDestroyed) return null;
            if (player.IsAdmin && config.AdminsBypass) return null;
            if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;
            if (buildingBlock.OwnerID == player.userID.Get()) return null;

            var privilege = buildingBlock.GetBuildingPrivilege();
            if (privilege != null && privilege.IsAuthed(player)) return null;

            if (config.NotifyPlayer)
            {
                player.ChatMessage(Msg("Blocked", player.UserIDString));
            }

            return true;
        }
    }
}

The plugin blocks rotation of building blocks a player does not own, unless they are authorized on the building's tool cupboard or are an admin. OnStructureRotate reads buildingBlock.OwnerID and compares it with player.userID.Get(). When the IDs differ it looks up the building privilege via buildingBlock.GetBuildingPrivilege() and asks IsAuthed(player); admins skip the check through a config toggle. A global on/off switch and a chat notice keep the server admins in control. Declining returns true, which cancels the rotation before the game touches the transform.

Common use cases

  • Stop griefing of neighbour bases

    Reject rotation when the player is not the block owner and not authorized on the cupboard, so raiders cannot reorient walls to break up a base interior.

  • Pin important structures

    Keep foundations and walls of a spawn area or event arena at a fixed orientation by returning true for any block inside a configured radius.

  • Log suspicious mass rotation

    Track rotation attempts per player per second and flag players spamming the rotate key near other players' buildings for admin review.

Pitfalls

  • Not all blocks reach the hook

    The game only calls DoRotation for definitions with canRotateAfterPlacement, and only after its own interaction and CanRotate checks pass. Blocks that fail those never hit your code.

  • Any non-null return cancels

    Returning false still cancels the rotation because the check is for a non-null result. Return null to allow, and a non-null value to block.

  • Ownership is not privilege

    OwnerID may belong to a player who placed the block, while the cupboard may be held by a teammate. Check both where teams or shared bases matter.

Build a plugin with OnStructureRotate

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

Prompt: Stop griefing of neighbour bases using the OnStructureRotate 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 OnStructureRotate

Generate