OnTeamMemberInvite
OnTeamMemberInvite is called when a player is about to send a team invite, both for nearby players and for remote/offline invites by Steam ID. Returning a non-null value cancels the invite.
object OnTeamMemberInvite(RelationshipManager.PlayerTeam playerTeam, BasePlayer player, ulong inviteeId, bool isOfflineInvite)Parameters
| Parameter | Type | Description |
|---|---|---|
playerTeam | RelationshipManager.PlayerTeam | The RelationshipManager.PlayerTeam object that is about to send the invite. Use it to read the team ID, leader or current member list. |
player | BasePlayer | The BasePlayer who is issuing the invite. This is the inviter, not the invitee; check their permissions or state here. |
inviteeId | ulong | The Steam ID being invited. For remote/offline invites the target may not be loaded, so resolve them with BasePlayer.FindAwakeOrSleepingByID if you need an entity. |
isOfflineInvite | bool | True when the invite goes through the offline/remote path (target resolved by ID), false when the target player entity was found nearby and the invite is sent on the spot. |
Return value
Return null (or nothing) to let the invite proceed. Returning any non-null value cancels the invite in both paths: at sendinvite the original call is skipped and the team never records the invite; at sendofflineinvite the same happens for the remote path.
How it works
The hook fires inside RelationshipManager.sendinvite and RelationshipManager.sendofflineinvite, right before the team actually records the invite. The local path (sendinvite) only runs when the target entity exists, is not the inviter, is not an NPC, has no team, and stands within 7 meters. The offline path (sendofflineinvite) resolves the target by ID via BasePlayer.FindAwakeOrSleepingByID, skips NPCs and players already on a team, and passes true for the last argument.
Use player to inspect the inviter's permissions, team size or role. Use playerTeam for the team ID and current members, and inviteeId to look up the recipient when you need more than the ID. The boolean tells you which code path you are in, which matters because an offline invitee may be null as an entity.
Declaring player as a more specific type such as BasePlayer is already the exact type here; narrowing further is not useful since the game passes a real BasePlayer. Declare the team parameter as RelationshipManager.PlayerTeam exactly or the hook will not be dispatched.
Example plugin: Cap team invites by permission
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Team Invite Guard", "RustPluginGenerator", "1.0.0")]
[Description("Rate-limits and caps team invites on the server.")]
public class TeamInviteGuard : RustPlugin
{
private const string PermBypass = "teaminviteguard.bypass";
private class PluginConfig
{
[JsonProperty("Invite cooldown seconds")]
public double CooldownSeconds = 30.0;
[JsonProperty("Maximum team size")]
public int MaxTeamSize = 8;
}
private PluginConfig config;
private readonly Dictionary<ulong, double> lastInvites = new Dictionary<ulong, double>();
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>
{
["Cooldown"] = "You can invite another player in {0} seconds.",
["TeamFull"] = "Your team is full ({0} members).",
["Invited"] = "You invited {0} to your team."
}, 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(PermBypass, this);
}
private object OnTeamMemberInvite(RelationshipManager.PlayerTeam playerTeam, BasePlayer player, ulong inviteeId, bool isOfflineInvite)
{
if (playerTeam == null || player == null) return null;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;
ulong inviterId = player.userID.Get();
double now = UnityEngine.Time.realtimeSinceStartup;
double last;
if (lastInvites.TryGetValue(inviterId, out last) && now - last < config.CooldownSeconds)
{
int wait = (int)Math.Ceiling(config.CooldownSeconds - (now - last));
player.ChatMessage(Msg("Cooldown", player.UserIDString, wait));
return true;
}
List<ulong> members = playerTeam.members;
if (members != null && members.Count >= config.MaxTeamSize)
{
player.ChatMessage(Msg("TeamFull", player.UserIDString, members.Count));
return true;
}
lastInvites[inviterId] = now;
return null;
}
private void Unload()
{
lastInvites.Clear();
}
}
}The plugin blocks or rate-limits invites to keep large public servers tidy. On every OnTeamMemberInvite it checks the inviter's userID against a short cooldown dictionary; if the player invited someone within the configured window, the hook returns a non-null value and the invite never reaches the team. It also counts current members of playerTeam and refuses invites once the team is at MaxTeamSize, unless the player has the bypass permission. Accepted invites are recorded in a dictionary keyed by Steam ID, with values cleared on a timer. The config exposes the cooldown seconds, the team cap and the bypass permission name, and all player feedback goes through the language file.
Common use cases
Block invites from muted or jailed players
Return a non-null value when the inviter is on a jail or mute list so they cannot recruit teammates while restricted.
Enforce a smaller team size
Read
playerTeam.members.Countand deny the invite once it reaches your configured cap, overriding the game default.Log remote invites separately
Use the
isOfflineInviteflag to record only remote invites for audit, since the target may be offline and outside your normal player checks.
Pitfalls
Returning any object blocks the invite
The patched call treats a non-null result as a cancel. Returning
true, a string or a player object all block it; always returnnullto allow.Offline invitee may not be spawned
In the offline path the target can be absent from the server, so do not assume
BasePlayer.FindAwakeOrSleepingByIDreturns an entity; fall back to the raw ID.Not called for pending accept step
This hook fires when the invite is sent, not when it is accepted or rejected. Use
OnTeamAcceptInviteorOnTeamRejectInvitefor that part of the flow.
Plugin recipes that use OnTeamMemberInvite
Build a plugin with OnTeamMemberInvite
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 OnTeamMemberInvite
Generate