Skip to content
RustPluginGenerator

OnEntityControl

OnEntityControl is called when the server checks whether a player is allowed to take control of a turret, CCTV camera or other remote-controlled entity, before the vanilla powered/booting checks run.

Signature
object OnEntityControl(AutoTurret autoTurret, ulong playerID)

Parameters

Hook parameters
ParameterTypeDescription
autoTurretAutoTurretThe entity whose control permission is being checked. Declared as AutoTurret here, but the same hook also fires for turrets, CCTV cameras and other remote-control entities, so declare a broader type such as RemoteControlEntity if you want to handle all of them.
playerIDulongThe Steam ID (ulong) of the player trying to take control of the entity. Use BasePlayer.FindByID(playerID) to resolve it to a player when you need more than the ID.

Return value

Return a bool to override the game's decision: false blocks the player from taking control and true allows it. Returning null (or anything that is not a bool) lets the original CanControl logic continue, so the turret's booting state, camera power state and other built-in checks still apply.

How it works

This hook fires from CanControl on AutoTurret, PoweredRemoteControlEntity and RemoteControlEntity. The game calls CanControl when a player attempts to use the entity's control interface — for example when the turret or camera is opened for computer-station control, so this is your chance to allow or deny that before the vanilla rules apply.

The two parameters are the entity being controlled and the Steam ID of the player requesting control. Because the call site is a plain CanControl and the hook fires before the vanilla booting / IsPowered() checks, a false result from your hook denies control entirely, while returning null leaves the decision to the game.

You can narrow the hook to a single type by declaring your parameter as AutoTurret (as in the signature) or as RemoteControlEntity to catch cameras, turret groups and similar devices. Declaring a more specific type than the entity being checked makes Oxide simply skip that call, so the plugin will not touch unrelated entities.

Note that CanControl is called frequently in turret/CCTV UIs, so keep the callback cheap and avoid logging inside it.

Other signatures

Oxide also calls OnEntityControl from other places in the game with these parameter types. Declare the overload you need, or several:

  • object OnEntityControl(PoweredRemoteControlEntity poweredRemoteControlEntity, ulong playerID)
  • object OnEntityControl(RemoteControlEntity remoteControlEntity, ulong playerID)

Example plugin: Restrict turret control to authorised players

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

namespace Oxide.Plugins
{
    [Info("Turret Control Limit", "RustPluginGenerator", "1.0.0")]
    [Description("Restricts who can take control of auto turrets based on permission, team and distance.")]
    public class TurretControlLimit : RustPlugin
    {
        private const string PermUse = "turretcontrollimit.use";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Require permission")]
            public bool RequirePermission = true;

            [JsonProperty("Maximum control distance (0 = unlimited)")]
            public float MaxDistance = 10f;

            [JsonProperty("Allow same team as owner")]
            public bool AllowOwnerTeam = true;

            [JsonProperty("Send denial message")]
            public bool SendDenial = 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 System.Collections.Generic.Dictionary<string, string>
            {
                ["NoPermission"] = "You do not have permission to control turrets.",
                ["TooFar"] = "You must be within {0}m of the turret to control it.",
                ["NotTeam"] = "Only the owning team may control this turret."
            }, 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(PermUse, this);
        }

        private object OnEntityControl(AutoTurret autoTurret, ulong playerID)
        {
            if (autoTurret == null || autoTurret.IsDestroyed) return null;

            BasePlayer player = BasePlayer.FindByID(playerID);
            if (player == null || player.IsAdmin) return null;

            if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse))
            {
                Deny(player, "NoPermission");
                return false;
            }

            if (IsOwnerTeam(player, autoTurret)) return null;

            if (config.MaxDistance > 0f &&
                Vector3.Distance(player.transform.position, autoTurret.transform.position) > config.MaxDistance)
            {
                Deny(player, "TooFar", config.MaxDistance);
                return false;
            }

            return null;
        }

        private bool IsOwnerTeam(BasePlayer player, AutoTurret autoTurret)
        {
            if (!config.AllowOwnerTeam || autoTurret.OwnerID == 0) return false;
            if (player.userID.Get() == autoTurret.OwnerID) return true;
            if (player.currentTeam == 0) return false;

            var team = RelationshipManager.ServerInstance.FindTeam(player.currentTeam);
            return team != null && team.members.Contains(autoTurret.OwnerID);
        }

        private void Deny(BasePlayer player, string key, params object[] args)
        {
            if (config.SendDenial) SendReply(player, Msg(key, player.UserIDString, args));
        }
    }
}

The plugin adds a configurable turretcontrol.use permission plus distance and team rules. When OnEntityControl fires for an AutoTurret, it resolves the player, rejects control if they lack the permission, if they are mounted, or if they are further than the configured range from the turret. Admins bypass the distance check. Returning false blocks control outright; returning null falls through to the vanilla logic. The config is validated on load and the permission is registered in Init, so a missing config never stops the server from starting.

Common use cases

  • Limit turret control by permission

    Only let players with a purchased or staff permission take control of turrets on your server, blocking griefers from hijacking deployed turrets.

  • Enforce proximity rules

    Deny control when the player is too far from the turret, preventing remote hijacking through walls or across the map.

  • Lock captured turrets to a team

    In team-based modes, refuse control from players outside the turret owner's team so raided turrets stay with the attackers who took them.

Pitfalls

  • Hook also fires for cameras

    The same hook is called from PoweredRemoteControlEntity and RemoteControlEntity, so a plugin that assumes every entity is an AutoTurret will miss CCTV cameras. Cast explicitly and decide what to do for other remote-controlled devices.

  • Returning a non-bool disables your override

    Only a bool return is honoured. Returning null, or anything that is not a bool, gives control back to the vanilla check, which is fine if that is your intent but easy to forget.

  • Called often, keep it cheap

    CanControl runs whenever the client polls control state, so avoid Puts, asset loads or heavy allocations in your handler; just resolve the player and apply your rule.

Build a plugin with OnEntityControl

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

Prompt: Limit turret control by permission using the OnEntityControl 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 OnEntityControl

Generate