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.
object OnVehicleLockRequest(ModularCarGarage modularCarGarage, BasePlayer player, string text)Parameters
| Parameter | Type | Description |
|---|---|---|
modularCarGarage | ModularCarGarage | The 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. |
player | BasePlayer | The 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. |
text | string | The 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
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.lockcarso 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,0or an empty string is a non-null value and blocks the request, so usenullexplicitly 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
textcomes 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.
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