OnBookmarksSendControl
OnBookmarksSendControl is called in ComputerStation.SendControlBookmarks just before the server sends the bookmark list to a player, and it fires with the station, the player and the generated bookmark payload.
object OnBookmarksSendControl(ComputerStation computerStation, BasePlayer player, string text)Parameters
| Parameter | Type | Description |
|---|---|---|
computerStation | ComputerStation | The ComputerStation entity whose bookmark list is being sent. Use `net.ID.Value` to identify the station or check `OwnerID` and position. |
player | BasePlayer | The BasePlayer receiving the bookmark RPC. This is the player who used the station, so permission and team checks belong here. |
text | string | The serialized bookmark string produced by `GenerateControlBookmarkString()`. It is the payload that would be sent to the client's computer station UI. |
Return value
Returning a non-null value suppresses the ReceiveBookmarks client RPC, so the player never receives the bookmark data. Returning null lets the original send continue normally. The method itself returns void, so the return value only acts as a block flag.
How it works
The hook runs inside ComputerStation.SendControlBookmarks, after the game builds the bookmark string with GenerateControlBookmarkString() and before the ReceiveBookmarks client RPC is issued. It fires every time the bookmark data for a computer station is pushed to a player: when a player mounts or uses the station and the game refreshes their bookmark list, and after bookmark changes that trigger a resend.
The computerStation parameter lets you identify the entity being controlled, for example by its network ID, owner or position. player is the recipient, so it is the right place for permission, team or proximity checks. text is the full payload; you can inspect it to see what would reach the client, but the hook cannot replace it.
Declaring a more specific type for player (such as BasePlayer) is already the signature default; if you narrowed it further to a derived type, Oxide would skip the call for other players. Null-check computerStation and player, since the hook only fires when the game already confirmed the player is not null, but the station reference should still be treated defensively.
Example plugin: Block bookmark sync on stations without the required permission
using System.Linq;
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Computer Bookmark Gate", "RustPluginGenerator", "1.0.0")]
[Description("Blocks computer station bookmark syncing for players without a permission")]
public class ComputerBookmarkGate : RustPlugin
{
private const string PermUse = "computerbookmarkgate.use";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastNotice = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Send notice to blocked players")]
public bool SendNotice { get; set; } = true;
[JsonProperty("Notice cooldown in seconds")]
public float NoticeCooldown { get; set; } = 30f;
}
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 computer station bookmarks.",
["Granted"] = "You granted {0} bookmark access.",
["Revoked"] = "You revoked {0} bookmark access.",
["Usage"] = "Usage: /bmgrant <partial name> or /bmrevoke <partial name>"
}, 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 OnBookmarksSendControl(ComputerStation computerStation, BasePlayer player, string text)
{
if (player == null) return null;
if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, PermUse)) return null;
if (config.SendNotice && computerStation != null)
{
float now = UnityEngine.Time.realtimeSinceStartup;
float last;
if (!lastNotice.TryGetValue(player.userID, out last) || now - last >= config.NoticeCooldown)
{
lastNotice[player.userID] = now;
player.ChatMessage(Msg("NoPermission", player.UserIDString));
}
}
return false;
}
[ChatCommand("bmgrant")]
private void CmdGrant(BasePlayer player, string command, string[] args)
{
if (player == null || !player.IsAdmin) return;
if (args == null || args.Length < 1)
{
player.ChatMessage(Msg("Usage", player.UserIDString));
return;
}
var target = FindPlayer(string.Join(" ", args));
if (target == null)
{
player.ChatMessage(Msg("Usage", player.UserIDString));
return;
}
permission.GrantUserPermission(target.UserIDString, PermUse, this);
player.ChatMessage(Msg("Granted", player.UserIDString, target.displayName));
}
[ChatCommand("bmrevoke")]
private void CmdRevoke(BasePlayer player, string command, string[] args)
{
if (player == null || !player.IsAdmin) return;
if (args == null || args.Length < 1)
{
player.ChatMessage(Msg("Usage", player.UserIDString));
return;
}
var target = FindPlayer(string.Join(" ", args));
if (target == null)
{
player.ChatMessage(Msg("Usage", player.UserIDString));
return;
}
permission.RevokeUserPermission(target.UserIDString, PermUse);
player.ChatMessage(Msg("Revoked", player.UserIDString, target.displayName));
}
private BasePlayer FindPlayer(string nameOrId)
{
if (string.IsNullOrEmpty(nameOrId)) return null;
var exact = BasePlayer.FindAwakeOrSleeping(nameOrId);
if (exact != null) return exact;
string lowered = nameOrId.ToLowerInvariant();
foreach (var candidate in BasePlayer.activePlayerList)
{
if (candidate != null && candidate.displayName.ToLowerInvariant().Contains(lowered)) return candidate;
}
return null;
}
private void Unload()
{
lastNotice.Clear();
}
}
}The plugin requires a permission to receive bookmark data on computer stations. When OnBookmarksSendControl fires, it checks if the player is an admin or holds computerbookmarkgate.use; if not, it returns a non-null value so the game skips the ReceiveBookmarks RPC and the player's bookmark list stays empty. The permission is registered in Init, and a chat command lets admins grant or revoke it in-game using the standard permission API. The station and payload are only read for a short info message to the player, which is rate-limited by a per-player cooldown dictionary to avoid chat spam on frequent resends.
Common use cases
Permission-gated bookmark lists
Restrict bookmark syncing to players with a specific permission, so the station UI cannot be used to store or share bookmark data on servers that treat it as a premium feature.
Audit bookmark payloads
Inspect
textto detect oversized or unusual bookmark strings before they reach the client, and log a warning when a player sends a list far larger than expected.Disable bookmarks globally
Return a non-null value for every call to effectively disable computer station bookmarks across the server without touching the game code.
Pitfalls
Return value blocks the RPC entirely
Any non-null return stops the
ReceiveBookmarksRPC, so the client keeps whatever stale bookmark state it had. There is no partial filtering of the payload with this hook.Fires on every resend
The game calls
SendControlBookmarkswhenever bookmark data is refreshed, which can be frequent. Avoid heavy work or chat messages in the hook without rate limiting.Player parameter can be null at the caller level
The hook only fires after the game checks
player != null, but defensive code keeps your handler safe if the assembly changes or the call is made from another path.
Build a plugin with OnBookmarksSendControl
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 OnBookmarksSendControl
Generate