Skip to content
RustPluginGenerator

OnVehicleLockRequest

OnVehicleLockRequest is called when a player asks a ModularCarGarage to add a lock to a car, before the game checks the resource cost and actually creates the lock. Returning a non-null value cancels the request.

Signature
object OnVehicleLockRequest(ModularCarGarage modularCarGarage, BasePlayer player, string text)

Parameters

Hook parameters
ParameterTypeDescription
modularCarGarageModularCarGarageThe garage entity the player is interacting with when the lock request arrives. Use it to read the car's position, its CarLock state, or to verify the caller is close to a specific vehicle.
playerBasePlayerThe player who sent the add-lock RPC. Already null-checked by the game before the hook fires, but null-check again for safety and use it for permission checks and replies.
textstringThe code string the player typed into the lock entry UI. It is what would become the code lock's code, so validate length and characters if you enforce a policy.

Return value

Returning null lets the original RPC continue: the game checks the lock resource cost, calls TryAddALock and takes the resources on success. Returning any non-null value stops the code path, so no lock is created and no resources are taken. The method returns void, so the value itself is never used as a result.

How it works

The hook fires inside ModularCarGarage.RPC_RequestAddLock, the RPC a client sends when the player confirms a code in the modular car lock dialog. At that point the game has already read the code string from the network message but has not yet verified the player can afford the lock resource, and has not called CarLock.TryAddALock. That makes the hook a natural checkpoint before anything is consumed.

modularCarGarage is the garage entity handling the request; use it to check distance, ownership or the current lock state. player is the requester, useful for permission checks and feedback messages. text is the submitted code and can be inspected or rejected (for example a minimum length or a ban on repeated digits).

The three parameters are concrete types, so declaring narrower parameters (such as BasePlayer) only works where the real argument matches; here they always do, so signature narrowing gains nothing. Declaring the parameters with their exact types is the safe choice.

Because the hook is not a per-tick or per-damage callback, sending a chat reply from it is acceptable. Avoid heavy work in it anyway, since RPCs can arrive repeatedly if a client spams the dialog.

Example plugin: Enforce length and permission rules on car lock codes

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

namespace Oxide.Plugins
{
    [Info("Vehicle Lock Policy", "RustPluginGenerator", "1.0.0")]
    [Description("Validates modular car lock codes and rate-limits add-lock requests.")]
    public class VehicleLockPolicy : RustPlugin
    {
        private const string PermLock = "vehiclelockpolicy.lockcar";

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

        private class PluginConfig
        {
            [JsonProperty("Minimum code length")]
            public int MinLength = 4;

            [JsonProperty("Require permission to place locks")]
            public bool RequirePermission = false;

            [JsonProperty("Request cooldown in seconds")]
            public float Cooldown = 2f;
        }

        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>
            {
                ["TooShort"] = "Your car lock code must be at least {0} characters long.",
                ["NoPermission"] = "You are not allowed to place locks on vehicles.",
                ["SlowDown"] = "You are placing locks too quickly, wait {0} seconds."
            }, 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(PermLock, this);
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player != null) lastRequest.Remove(player.userID);
        }

        private object OnVehicleLockRequest(ModularCarGarage modularCarGarage, BasePlayer player, string text)
        {
            if (player == null || modularCarGarage == null) return null;

            // Rate limit the RPC before doing any other work.
            float now = UnityEngine.Time.realtimeSinceStartup;
            float last;
            if (config.Cooldown > 0f && lastRequest.TryGetValue(player.userID, out last) && now - last < config.Cooldown)
            {
                player.ChatMessage(Msg("SlowDown", player.UserIDString, config.Cooldown));
                return true;
            }
            lastRequest[player.userID] = now;

            if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermLock))
            {
                player.ChatMessage(Msg("NoPermission", player.UserIDString));
                return true;
            }

            string code = text ?? string.Empty;
            if (code.Length < config.MinLength)
            {
                player.ChatMessage(Msg("TooShort", player.UserIDString, config.MinLength));
                return true;
            }

            return null;
        }

        private void Unload()
        {
            lastRequest.Clear();
        }
    }
}

The plugin intercepts every modular car lock request and applies two rules from config: a minimum code length and an optional permission requirement. It also keeps a per-player throttle so a client cannot spam the add-lock RPC. When a rule fails, the hook returns a non-null value, which cancels the request before the game checks the lock cost or calls TryAddALock, and the player gets a localized chat message. When everything passes, the hook returns null and the vanilla flow runs untouched. The throttle map is cleared on player disconnect to avoid leaking entries, and configuration is validated on load so a corrupt file falls back to defaults.

Common use cases

  • Enforce code complexity

    Reject codes shorter than a configured length or made of repeated digits, so parked cars on a busy server are not protected by trivial codes that raiders guess quickly.

  • Restrict locking to permitted groups

    Require a permission such as vehiclelockpolicy.lockcar so only VIP or trusted players can place locks on modular cars, while everyone else keeps the vanilla behavior of no lock.

  • Rate-limit lock RPC spam

    Track the last request per player and cancel requests that arrive faster than a configured cooldown, which reduces the cost of repeated RPC handling and tells the player to slow down.

Pitfalls

  • Returning false or 0 still cancels

    The check is simply whether the hook returned null. Returning false, 0 or an empty string is a non-null value and blocks the request, so use null explicitly for the allow path.

  • The lock cost is checked after the hook

    Your code runs before the resource affordability check, so a player with insufficient resources can still reach your hook and receive your message before vanilla rejects the request. Do not assume the lock will be created just because you allowed it.

  • Code text is unvalidated input

    text comes straight from the client message. Bound its length before storing or echoing it, and never build paths or commands from it.

Build a plugin with OnVehicleLockRequest

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

Prompt: Enforce code complexity using the OnVehicleLockRequest 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 OnVehicleLockRequest

Generate