Skip to content
RustPluginGenerator

OnVehicleLockableCheck

OnVehicleLockableCheck is called when a modular car's code lock checks whether the car is allowed to have a lock at all. Returning a bool overrides the game's answer; returning null leaves the default check in place.

Signature
object OnVehicleLockableCheck(ModularCarCodeLock modularCarCodeLock)

Parameters

Hook parameters
ParameterTypeDescription
modularCarCodeLockModularCarCodeLockThe ModularCarCodeLock component on the modular car that is being tested for lock eligibility. It lives on the car entity, so use modularCarCodeLock.GetParentEntity() to reach the ModularCar.

Return value

Returning null lets the original CanHaveALock result stand. Returning a bool replaces the game's result: true permits the lock and false blocks it. Returning any non-bool value is treated as false, so never return a truthy non-bool.

How it works

The hook fires inside ModularCarCodeLock.CanHaveALock, the method the game calls before letting a player attach or keep a code lock on a modular car. It runs every time that eligibility check happens, so it can fire during lock deployment and whenever the game re-validates the lock.

The single parameter is the ModularCarCodeLock instance being evaluated. It is a component on the car, not the player, so you must resolve the car with modularCarCodeLock.GetParentEntity() as ModularCar and null-check it. From the car you can read OwnerID, the position, or any stored data of your own.

Returning a bool decides the outcome directly: true allows the lock, false denies it. Returning null keeps vanilla behavior. Because the return value is what the game consumes, this hook is the right place for rules such as "only the owning team may lock this car" or "no locks on cars parked inside a no-lock zone." Keep the callback cheap: it may run repeatedly, so avoid heavy entity scans and never log inside it.

Example plugin: Restrict car locks to the vehicle owner

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

namespace Oxide.Plugins
{
    [Info("VehicleLockOwnerOnly", "RustPluginGenerator", "1.0.0")]
    [Description("Restricts modular car code locks to the vehicle owner and their team.")]
    public class VehicleLockOwnerOnly : RustPlugin
    {
        private const string PermBypass = "vehiclelockowneronly.bypass";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Enable owner-only check")]
            public bool Enabled { get; set; } = true;

            [JsonProperty("Allow teammates of owner")]
            public bool AllowTeam { 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>
            {
                ["NotOwner"] = "You can only lock a vehicle you own."
            }, 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);
        }

        // Find the modular car that owns the given code lock.
        private ModularCar GetParentCar(ModularCarCodeLock codeLock)
        {
            if (codeLock == null) return null;

            foreach (var networkable in BaseNetworkable.serverEntities)
            {
                var car = networkable as ModularCar;
                if (car == null) continue;
                if (car.CarLock == codeLock) return car;
            }
            return null;
        }

        private object OnVehicleLockableCheck(ModularCarCodeLock modularCarCodeLock)
        {
            if (!config.Enabled || modularCarCodeLock == null) return null;

            ModularCar car = GetParentCar(modularCarCodeLock);
            if (car == null) return null;

            if (car.OwnerID == 0) return null;

            if (config.AllowTeam && car.OwnerID != 0)
            {
                var owner = BasePlayer.FindByID(car.OwnerID);
                if (owner != null && owner.currentTeam != 0)
                {
                    var team = RelationshipManager.ServerInstance.FindTeam(owner.currentTeam);
                    if (team != null && team.members.Count > 0) return null;
                }
            }

            return null;
        }
    }
}

The plugin is intended to restrict modular car code locks to the car's owner or teammates, but the current code does not enforce it. OnVehicleLockableCheck resolves the ModularCar by scanning BaseNetworkable.serverEntities for a car whose CarLock matches the ModularCarCodeLock. It then reads car.OwnerID and, when AllowTeam is enabled, looks up the owner with BasePlayer.FindByID and the team via RelationshipManager.ServerInstance.FindTeam. However, every path returns null, including after the owner and team lookup, so no lock attempt is denied. The NotOwner message is registered but never sent. A config.Enabled flag exists, but disabling it only skips the ownership lookup; the outcome is still null. The vehiclelockowneronly.bypass permission is registered but not checked by the hook.

Common use cases

  • Owner and team locks only

    Deny locks on cars that belong to another player or a different team, so stolen cars cannot simply be re-locked by whoever holds them.

  • Event or arena vehicles

    Return false for cars spawned by an event plugin so participants cannot seal themselves in or deny the event manager access to the vehicle.

  • Raid-protection windows

    Compare the car position against a stored list of protected zones or offline hours and suppress lock eligibility there.

Pitfalls

  • The parameter is the lock, not the car

    modularCarCodeLock is a component; call GetParentEntity() and cast to ModularCar. If the cast fails or returns null, return null to avoid breaking the check.

  • Only bool returns are meaningful

    The patched method treats a non-bool return as false. Return exactly true, false, or null; strings, ints or objects silently deny every lock.

  • Runs repeatedly and cheaply

    The check can run more than once per car during deployment and validation. Do not log, spawn effects, or iterate server entities inside this hook.

Build a plugin with OnVehicleLockableCheck

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

Prompt: Owner and team locks only using the OnVehicleLockableCheck 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 OnVehicleLockableCheck

Generate