OnSignLocked
OnSignLocked is called after a player locks a sign, right after the game sets the Locked flag, sends a network update and assigns ownership to that player.
void OnSignLocked(Signage signage, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
signage | Signage | The Signage entity that was just locked (a sign, banner or similar). Read its net.ID, transform position or OwnerID to act on the specific sign; it is already flagged Locked and owned by the player when the hook fires. |
player | BasePlayer | The BasePlayer who locked the sign. Use it for permission checks, messaging, and to attribute the action to a player id. |
Return value
Returning a value has no effect. The injection uses the return value only as a continue signal, and Signage.LockSign and PhotoFrame.LockSign return void, so the lock has already completed by the time the hook runs.
How it works
The hook fires from Signage.LockSign and PhotoFrame.LockSign, after the game has already confirmed the player can interact and is allowed to update the sign. By the time it runs, SetFlagLocal(Flags.Locked, true) has been applied, a network update was sent, and OwnerID is set to the locking player's id. Because it fires after those changes, you cannot use this hook to block a lock; the sign is already locked and owned.
signage is the locked entity itself. Use signage.net.ID.Value for a stable identifier, signage.transform.position for a location, or signage.ShortPrefabName to distinguish sign types. player is the lock owner, useful for permission checks, messages and logging a player id.
The hook also fires for photo frames, which pass a PhotoFrame instance. If you declare PhotoFrame instead of Signage, Oxide only calls your method for photo frames. Declaring Signage covers both because PhotoFrame derives from it, so an instance check still passes. Declare BasePlayer for player if you only need the common player members.
Practical uses are tracking, notification and post-lock automation, not prevention. Unlocking and relocking a sign triggers the hook again each time the flag is set.
Other signatures
Oxide also calls OnSignLocked from other places in the game with these parameter types. Declare the overload you need, or several:
void OnSignLocked(PhotoFrame photoFrame, BasePlayer player)
Example plugin: Restrict sign locking to a permission
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Sign Lock Permission", "RustPluginGenerator", "1.0.0")]
[Description("Restricts sign locking to a permission and tracks locked signs")]
public class SignLockPermission : RustPlugin
{
private const string PermUse = "signlockpermission.use";
private PluginConfig config;
private Dictionary<ulong, ulong> lockedSigns = new Dictionary<ulong, ulong>();
private class PluginConfig
{
[JsonProperty("Notify owner on lock")]
public bool NotifyOwner { 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 are not allowed to lock signs.",
["Locked"] = "Sign locked. It is now owned by you.",
["Unlocked"] = "This sign was unlocked because you lack permission."
}, this);
}
private void Init()
{
permission.RegisterPermission(PermUse, this);
lockedSigns = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, ulong>>(Name) ?? new Dictionary<ulong, ulong>();
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, lockedSigns);
}
private void OnSignLocked(Signage signage, BasePlayer player)
{
if (signage == null || player == null) return;
if (signage.net == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermUse))
{
// Signage is a BaseCombatEntity; clear its lock and ownership instead.
signage.OwnerID = 0UL;
signage.SendNetworkUpdate();
player.ChatMessage(Msg("Unlocked", player.UserIDString));
return;
}
lockedSigns[signage.net.ID.Value] = player.userID.Get();
if (config.NotifyOwner)
player.ChatMessage(Msg("Locked", player.UserIDString));
}
private string Msg(string key, string userId = null, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
}
}The plugin registers signlockpermission.use and checks it in OnSignLocked. Because the game has already locked the sign and set the owner before the hook runs, the plugin cannot stop the lock directly. Instead, when the player lacks permission it clears the sign's ownership with signage.OwnerID = 0UL and calls SendNetworkUpdate(), then sends a chat message from the language file. When the player does have permission, it records the lock in a small data file keyed by the sign's net ID and, if NotifyOwner is enabled, sends the Locked chat message to the player who locked it. Unload saves the tracked data through Interface.Oxide.DataFileSystem. The config holds a toggle for notifications.
Common use cases
Log sign ownership
Record which player locked each sign and when, so admins can trace griefing or disputed builds.
Enforce a lock permission
Check a permission in the hook and unlock signs locked by players who lack it, giving them a chat warning.
Notify the owner
Send a message or server broadcast confirming the sign is now locked, and optionally the grid location.
Pitfalls
The lock has already happened
The hook fires after the Locked flag and OwnerID are set, so returning a value does not prevent the lock. To undo it, clear the flag and reset ownership yourself.
Photo frames use a different type
PhotoFrame.LockSign passes a PhotoFrame. Declaring Signage covers both; declaring PhotoFrame narrows the hook to photo frames only.
Re-locking retriggers the hook
Unlocking and locking a sign again fires the hook each time the flag is set, so avoid assuming it runs only once per sign.
Build a plugin with OnSignLocked
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 OnSignLocked
Generate