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.
object OnEntityControl(AutoTurret autoTurret, ulong playerID)Parameters
| Parameter | Type | Description |
|---|---|---|
autoTurret | AutoTurret | The 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. |
playerID | ulong | The 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
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
PoweredRemoteControlEntityandRemoteControlEntity, so a plugin that assumes every entity is anAutoTurretwill miss CCTV cameras. Cast explicitly and decide what to do for other remote-controlled devices.Returning a non-bool disables your override
Only a
boolreturn is honoured. Returningnull, or anything that is not abool, gives control back to the vanilla check, which is fine if that is your intent but easy to forget.Called often, keep it cheap
CanControlruns whenever the client polls control state, so avoidPuts, 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.
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