Skip to content
RustPluginGenerator

OnRotateVendingMachine

OnRotateVendingMachine is called when a player presses the rotate button on a vending machine, before the machine checks its own rotation state and flips itself 180 degrees.

Signature
object OnRotateVendingMachine(VendingMachine vendingMachine, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
vendingMachineVendingMachineThe VendingMachine being rotated. Use it to read the shop state, owner, position or to check whether the machine has any offers before deciding.
playerBasePlayerThe BasePlayer who pressed the rotate button. It comes from the RPC message player field, so it is the client requesting the rotation; check it for null before reading permissions or building rights.

Return value

Returning null or nothing leaves the call chain untouched, so the game runs CanRotate(), build rights and empty inventory checks and flips the machine if they pass. Returning any non-null object (a true bool, a string, a number) short-circuits the original code, so the machine never rotates.

How it works

The hook fires inside VendingMachine.RPC_RotateVM, the client RPC sent when a player uses the rotate control on a vending machine. It runs before the game calls CanRotate() and before the msg.player.CanBuild() / IsInventoryEmpty() checks that actually flip transform.rotation. Because of that ordering you see the request even when the machine is currently busy (for example while a sale is in progress or the inventory is not empty).

vendingMachine lets you inspect the shop: its position, OwnerID, inventory contents and flags. player is the requesting player โ€” the one whose build rights and access matter. You can narrow player to a more specific subtype only if you are certain the client is that type; for a plain player request it is best left as BasePlayer.

The return value is the only control you get. Returning anything non-null cancels the rotation entirely and the machine keeps its facing. Returning null lets the stock game logic decide using its own CanRotate, build permission and empty-inventory rules. Do not send chat messages from here unless you first confirm the request is intentional; the RPC can be triggered repeatedly.

Example plugin: Rotate vending machines by 90 degrees instead of 180

VendingQuarterTurn.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Vending Quarter Turn", "RustPluginGenerator", "1.0.0")]
    [Description("Rotates vending machines 90 degrees in the direction the player is facing instead of the vanilla 180 degree flip")]
    public class VendingQuarterTurn : RustPlugin
    {
        private const string PermAdmin = "vendingquarterturn.admin";

        private PluginConfig config;
        private readonly Dictionary<ulong, float> lastRotate = new Dictionary<ulong, float>();

        private class PluginConfig
        {
            [JsonProperty("Cooldown in seconds")]
            public float Cooldown { get; set; } = 2f;

            [JsonProperty("Require empty inventory")]
            public bool RequireEmpty { 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>
            {
                ["Cooldown"] = "You can rotate this machine again in {0}s.",
                ["NotEmpty"] = "Empty the vending machine before rotating it.",
                ["NoBuild"] = "You need building privilege here to rotate this machine."
            }, 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 Unload()
        {
            lastRotate.Clear();
        }

        private object OnRotateVendingMachine(VendingMachine vendingMachine, BasePlayer player)
        {
            if (vendingMachine == null || player == null || !player.IsConnected)
                return null;

            bool isAdmin = permission.UserHasPermission(player.UserIDString, PermAdmin);
            if (player.CanBuild() == false && !isAdmin)
            {
                player.ChatMessage(Msg("NoBuild", player.UserIDString));
                return true;
            }

            if (config.RequireEmpty && !isAdmin && vendingMachine.inventory != null && !vendingMachine.inventory.IsEmpty())
            {
                player.ChatMessage(Msg("NotEmpty", player.UserIDString));
                return true;
            }

            ulong id = vendingMachine.net != null ? vendingMachine.net.ID.Value : 0UL;
            float now = Time.realtimeSinceStartup;
            float last;
            if (id != 0UL && lastRotate.TryGetValue(id, out last) && now - last < config.Cooldown)
            {
                player.ChatMessage(Msg("Cooldown", player.UserIDString, Mathf.CeilToInt(config.Cooldown - (now - last))));
                return true;
            }

            Vector3 forward = player.eyes != null ? player.eyes.HeadForward() : player.transform.forward;
            forward.y = 0f;
            if (forward.sqrMagnitude < 0.01f)
                return null;

            vendingMachine.transform.rotation = Quaternion.LookRotation(-forward.normalized, Vector3.up);
            vendingMachine.SendNetworkUpdate();

            if (id != 0UL)
                lastRotate[id] = now;

            return true;
        }
    }
}

Vanilla rotation always flips a vending machine 180 degrees, which is useless when you only need a quarter turn. This plugin intercepts OnRotateVendingMachine, cancels the stock behavior by returning true, then applies its own 90 degree yaw in the direction the requesting player is looking. It reuses the game's own conditions: the player must have build rights (CanBuild()) and the machine inventory must be empty. A short cooldown per machine ID prevents spam from repeated RPCs. Staff with the vendingquarterturn.admin permission can rotate even when the machine still holds stock, which is handy while setting up a shop.

Common use cases

  • Allow only owners to rotate

    Compare player.userID against vendingMachine.OwnerID and return non-null for anyone else, so third parties cannot reorient a shop that faces a road.

  • Block rotation while the shop is stocked

    Return a non-null value when vendingMachine.inventory holds items, so admins do not accidentally move a machine that sells items to other players.

  • Add a cooldown or logging

    Return non-null when the same machine asked recently, or store the requesting player and machine ID into a data file to audit rotations on shared servers.

Pitfalls

  • The hook runs before the game's own checks

    Your hook fires before CanRotate() and the build / inventory tests, so a non-null return cancels the rotation even if the game would have refused it anyway. Do not assume the player is allowed just because the hook fired.

  • player can be null

    The parameter is taken from the RPC message and can be null if the connection dropped. Always null-check before calling CanBuild() or reading permission data.

  • Non-null means blocked

    This hook is checked for a non-null value, not for true or false. Returning false still cancels rotation โ€” return null to allow it and any object to deny it.

Build a plugin with OnRotateVendingMachine

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

Prompt: Allow only owners to rotate using the OnRotateVendingMachine 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 OnRotateVendingMachine

Generate