OnApartmentMasterKeyPurchase
OnApartmentMasterKeyPurchase is called when a player interacts with an apartment security terminal to buy a master key, before the scrap price is charged. Returning a non-null value cancels the purchase.
object OnApartmentMasterKeyPurchase(BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer who is buying the apartment master key. Check it for null before using it; it is the only context the hook provides, so player.userID and player.transform.position are the usual entry points for custom logic. |
Return value
Returning null lets the purchase proceed normally: the game continues to the scrap lookup and the price deduction. Returning any non-null object (for example a string or a bool) stops the original method immediately, so no scrap is taken and no key is issued.
How it works
The hook fires from NPCApartmentSecurity.OnPurchaseKey, which the game runs once a player triggers a master key purchase at an apartment security terminal. It runs before the scrap item definition is looked up and before the configured masterkeyprice is taken, so at the moment of the call no items have been removed from the player yet. The only argument is the buying BasePlayer, which is enough to gate the purchase by permission, team, remaining scrap, building privilege or a cooldown of your own. There is no overload with additional data, so anything else (the terminal position, the price, the player's current balance) has to be read from the player or from the server-side ApartmentCommands.masterkeyprice field you configure yourself. Because the hook is checked with a valid-type test against a void method, any non-null return aborts the original path silently: the player gets no message from the game, so send your own denial text through chat or lang before returning a value.
Example plugin: Permission-gated apartment master key purchase
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("ApartmentKeyGate", "RustPluginGenerator", "1.0.0")]
[Description("Restricts apartment master key purchases to players with a permission and a scrap balance.")]
public class ApartmentKeyGate : RustPlugin
{
private const string PermBuy = "apartmentkeygate.buy";
private const int ScrapItemId = -932201673;
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Required permission")]
public bool UsePermission { get; set; } = true;
[JsonProperty("Minimum scrap balance")]
public int MinimumScrap { get; set; } = 200;
[JsonProperty("Exempt admins")]
public bool ExemptAdmins { 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 buy an apartment master key.",
["NotEnoughScrap"] = "You need at least {0} scrap to buy an apartment master key.",
["PurchaseAllowed"] = "Your purchase is being processed, the key will be charged to your inventory."
}, this);
}
private string Msg(string key, string userId = null, params object[] args)
{
return string.Format(lang.GetMessage(key, this, userId), args);
}
private void Init()
{
permission.RegisterPermission(PermBuy, this);
}
private object OnApartmentMasterKeyPurchase(BasePlayer player)
{
if (player == null || !player.IsConnected) return null;
if (config.UsePermission && !permission.UserHasPermission(player.UserIDString, PermBuy) && !(config.ExemptAdmins && player.IsAdmin))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return true;
}
int scrap = player.inventory != null ? player.inventory.GetAmount(ScrapItemId) : 0;
if (scrap < config.MinimumScrap)
{
player.ChatMessage(Msg("NotEnoughScrap", player.UserIDString, config.MinimumScrap));
return true;
}
player.ChatMessage(Msg("PurchaseAllowed", player.UserIDString));
return null;
}
}
}The plugin registers a single permission, apartmentkeygate.buy, and checks it inside OnApartmentMasterKeyPurchase. Players without the permission are told through the lang message NoPermission, and the hook returns true so the game never reaches the scrap deduction or the key handout. Players holding the permission pass through with null. An optional config toggle lets admins exempt server admins and team leaders from the check, and a second string message is sent when the purchase is allowed, which is useful for confirming the price is about to be taken.
Common use cases
Restrict master keys to a permission group
Gate apartment key sales behind a donor or VIP permission and return a non-null value to cancel for everyone else. Configure the permission in a config file so admins can change which group is allowed.
Require a minimum scrap balance
Read the player's main inventory with inventory.GetAmount on the scrap item id and cancel the purchase when the balance is below a configured threshold plus the current master key price.
Limit purchases per player
Track how many keys each Steam ID has bought in a data file and return a denial once the configured cap is reached, resetting counts on wipe with the OnNewSave hook.
Pitfalls
Returning a value gives no feedback by itself
The game does not tell the player why the purchase was blocked. Always send a chat message or lang reply before returning non-null, otherwise the terminal appears broken.
The hook fires before the scrap is taken
No item has been removed at this point, so any balance check you make must account for the price the game will then deduct. Comparing only against the price can leave the player unable to pay.
Server-side price changes are global
ApartmentCommands.masterkeypriceis a shared field, not per player. Changing it from the hook affects every future purchase, so prefer canceling the call instead of mutating the price.
Build a plugin with OnApartmentMasterKeyPurchase
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 OnApartmentMasterKeyPurchase
Generate