Skip to content
RustPluginGenerator

CanNetworkTo

CanNetworkTo is called when the server decides whether a networkable entity should be sent to a specific player's client. Returning false stops replication of that entity to that player until the next subscription evaluation.

Signature
object CanNetworkTo(BaseNetworkable entity, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
entityBaseNetworkableThe networkable entity that the server is deciding whether to replicate to the given player. For the BasePlayer override this is the player being networked to the observer.
playerBasePlayerThe receiving BasePlayer (the client whose network subscription is being evaluated). Never null in the base path, but always null-check before reading members.

Return value

Returning null lets the game's default ShouldNetworkTo logic run unchanged. Returning a bool short-circuits the original method: true marks the pair as networkable without running the default group/occlusion checks, and false hides the entity from that player until the next evaluation. Any other return type is ignored.

How it works

This hook fires from BaseNetworkable.ShouldNetworkTo, which the server runs for every entity/player pair it is about to add to a network group, and from the BasePlayer.ShouldNetworkTo override for player-to-player visibility. It is a per-pair decision: the server asks whether entity should be replicated to player. The base implementation checks the entity's network group and distance/occlusion rules; your hook runs before that logic.

Because the hook is called very often (every subscription pass, every spawn), keep the body cheap: avoid LINQ, allocations, and disk or chat output. Cache what you need in OnServerInitialized. Declaring a more specific entity type (for example BasePlayer) is not enough to isolate the override call, because Oxide dispatches by argument type only and the base path also passes arbitrary BaseNetworkable instances that will fail the type check and be skipped by Oxide, silently changing behavior for entities you did not intend to filter. If you need to act on players specifically, compare entity as BasePlayer inside the hook instead.

Returning false hides the entity from that player's client; other players still receive it. If you hide an entity that the client references elsewhere, expect visual artifacts, missing colliders, or loot UI errors until you allow it again.

Other signatures

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

  • object CanNetworkTo(BasePlayer player, BasePlayer player2)

Example plugin: Hide players outside a permission group's view distance

NetworkRangeLimit.cs
using System;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Network Range Limit", "RustPluginGenerator", "1.0.0")]
    [Description("Hides distant players from observers in a permission group to reduce client exposure.")]
    public class NetworkRangeLimit : RustPlugin
    {
        private const string PermRestricted = "networkrangelimit.restricted";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Maximum visible distance (meters)")]
            public float MaxDistance = 250f;

            [JsonProperty("Only apply to players with the permission")]
            public bool OnlyRestricted = 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);

        private void Init()
        {
            permission.RegisterPermission(PermRestricted, this);
        }

        private object CanNetworkTo(BaseNetworkable entity, BasePlayer player)
        {
            if (entity == null || player == null || config.MaxDistance <= 0f) return null;

            var observer = player;
            var subject = entity as BasePlayer;
            if (subject == null || subject == observer) return null;
            if (!observer.IsConnected || !subject.IsConnected) return null;

            if (config.OnlyRestricted && !permission.UserHasPermission(observer.UserIDString, PermRestricted))
                return null;

            float maxSqr = config.MaxDistance * config.MaxDistance;
            float dx = observer.transform.position.x - subject.transform.position.x;
            float dy = observer.transform.position.y - subject.transform.position.y;
            float dz = observer.transform.position.z - subject.transform.position.z;
            if ((dx * dx) + (dy * dy) + (dz * dz) > maxSqr)
                return false;

            return null;
        }
    }
}

The plugin lets admins restrict how far certain players can see other players by adding them to a permission. In CanNetworkTo it checks only player-to-player pairs by casting entity as BasePlayer. If the observer lacks the permission and the entity is a player beyond the configured distance, it returns false, hiding that player's networkable from the observer's client. Distance is measured in world units using squared components to avoid a square root on every call, and the threshold comes from config. Everything else returns null so vanilla behavior is preserved. The hook stays allocation-light: one cast, one permission check, one distance comparison.

Common use cases

  • Anti-cheat style fog of war

    Prevent exploitation clients from discovering remote players by hiding players beyond a configurable distance from restricted accounts, while normal players keep default visibility.

  • Event or arena isolation

    During an event, hide all players outside the arena bounds from participants by returning false for pairs that are not both inside the region, avoiding outside interference and stream sniping.

  • Staff invisibility

    Hide a spectator or admin entity from regular players by checking the entity's owner or a marker component and returning false while leaving other players' visibility untouched.

Pitfalls

  • Called extremely often

    The hook runs for every entity/player subscription pass, so PrintWarning, LINQ, and closures inside the body will cause measurable load on populated servers. Precompute data in OnServerInitialized and store it in dictionaries.

  • Type-narrowing silently skips calls

    Declaring BasePlayer entity in the parameters makes Oxide skip every call where the entity is not a player, which changes vanilla behavior for structures, items, and NPCs. Keep the parameter as BaseNetworkable and cast inside.

  • Hiding entities breaks clients

    Returning false for lootable containers, doors, or players the client already knows about can produce missing colliders, stuck UI, or desync until the pair is evaluated again. Only hide entities that are safe to omit from the client's view.

Build a plugin with CanNetworkTo

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

Prompt: Anti-cheat style fog of war using the CanNetworkTo 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 CanNetworkTo

Generate