Skip to content
RustPluginGenerator

OnPhoneCallStart

OnPhoneCallStart is called when a phone begins placing an outgoing call, before the game proceeds with connecting the handset to its target. Returning a non-null value cancels the call.

Signature
object OnPhoneCallStart(PhoneController phoneController, PhoneController activeCallTo, BasePlayer currentPlayer)

Parameters

Hook parameters
ParameterTypeDescription
phoneControllerPhoneControllerThe PhoneController of the phone that is placing the call, i.e. the caller's handset. Use it to read its position, owner ID or network ID.
activeCallToPhoneControllerThe PhoneController on the receiving end of the call. May be null when the phone has no target set yet, so null-check before reading it.
currentPlayerBasePlayerThe BasePlayer who is starting the call. Can be null in edge cases, so guard against it before using inventory, team or permission data.

Return value

Returning null lets the call continue to the game's normal logic. Returning any non-null object cancels the original code path inside PhoneController.BeginCall, so the call is not placed. Since the method returns void, the actual value you return only matters as a signal; true is the conventional choice.

How it works

The hook fires at the top of PhoneController.BeginCall, which runs when a player uses a telephone in Rust to dial out to another handset. phoneController is the caller's handset, activeCallTo is the handset being called (this can be null if no target has been assigned yet), and currentPlayer is the player using the phone. The hook runs before the game checks whether the phone is a mobile handset and whether the target requires power, so anything you do here happens before any call state is established.

Because the dispatch only checks that each argument matches the declared parameter type, declaring BasePlayer currentPlayer (as in the signature) is the normal choice. You cannot narrow PhoneController to a more specific type since there is nothing below it to narrow to. Null-check activeCallTo and currentPlayer; when a call is placed through an unusual path one of them can be absent.

This is the place to enforce rules such as a permission gate, a cooldown between calls, blocking calls during a server event, or logging who dials whom. The hook can fire on every dial attempt, so keep the body cheap and avoid logging unless a debug flag is enabled.

Example plugin: Block phone calls without a permission

PhoneCallPermission.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Phone Call Permission", "RustPluginGenerator", "1.0.0")]
    [Description("Requires a permission before a player can place an outgoing phone call.")]
    public class PhoneCallPermission : RustPlugin
    {
        private const string PermUse = "phonecallpermission.use";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Notify player when call is blocked")]
            public bool NotifyBlocked { get; set; } = true;

            [JsonProperty("Admins bypass permission")]
            public bool AdminsBypass { 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>
            {
                ["NoPermission"] = "You do not have permission to use the telephone."
            }, this);
        }

        private string Msg(string key, string userId = null) => lang.GetMessage(key, this, userId);

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

        private object OnPhoneCallStart(PhoneController phoneController, PhoneController activeCallTo, BasePlayer currentPlayer)
        {
            if (currentPlayer == null || currentPlayer.IsNpc)
                return null;

            if (config.AdminsBypass && currentPlayer.IsAdmin)
                return null;

            if (permission.UserHasPermission(currentPlayer.UserIDString, PermUse))
                return null;

            if (config.NotifyBlocked)
                currentPlayer.ChatMessage(Msg("NoPermission", currentPlayer.UserIDString));

            return true;
        }
    }
}

The plugin registers phonecallpermission.use in Init and gives administrators access automatically. When OnPhoneCallStart fires it verifies currentPlayer and the permission, and returns true to cancel the call when the player is not authorised. Denied players additionally receive a chat message from the language file, and the config controls both the denial message toggle and whether admins bypass the check. Because the hook fires on each dial, the permission lookup is the only work done on the hot path; there is no periodic timer or global state.

Common use cases

  • Permission-gated telephone

    Allow only players with a specific permission to place outgoing calls, for example on a VIP-only server or during a restricted event.

  • Call cooldown

    Record the last call time per player ID in a dictionary and return non-null when a new call is attempted before the cooldown expires.

  • Audit log of dial attempts

    Write the caller's name and the target handset's owner to a data file so staff can review who is spamming the phone network.

Pitfalls

  • activeCallTo can be null

    The receiving handset may not be set when the hook runs. Always null-check it before reading its owner or network ID, otherwise you will throw inside the hook.

  • Hook fires before phone state is established

    Anything the game does after the injection (mobile checks, power requirements) has not run yet, so do not assume the call is actually in progress inside this hook.

  • Do not log on every call

    Busy servers can see many dial attempts from the same player. Guard any Puts or chat output behind a debug flag so it does not spam the console.

Build a plugin with OnPhoneCallStart

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

Prompt: Permission-gated telephone using the OnPhoneCallStart 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 OnPhoneCallStart

Generate