OnTeamDisband
OnTeamDisband is called when the server is about to remove a player team, before its members are cleared and the team object is returned to the pool. Returning a non-null value cancels the removal.
object OnTeamDisband(RelationshipManager.PlayerTeam teamToDisband)Parameters
| Parameter | Type | Description |
|---|---|---|
teamToDisband | RelationshipManager.PlayerTeam | The RelationshipManager.PlayerTeam instance the game is about to remove. Read teamID, members and teamLeader from it before deciding whether to cancel the disband. |
Return value
Returning null (or not implementing the hook) lets the server proceed: the team is removed from the team list, OnTeamDisbanded fires, and the team object is freed. Returning any non-null value skips that block entirely, so the team stays registered and OnTeamDisbanded is not called.
How it works
The hook fires inside RelationshipManager.DisbandTeam, the single method the server uses for every team removal: a leader pressing the disband option, the last member leaving, and server-side cleanup such as a player becoming the only member and the team being torn down by the game. The call happens before teams.Remove(teamToDisband.teamID) and before the subsequent OnTeamDisbanded notification, so at this point the team still exists in the manager, members are still populated, and teamToDisband.teamID is still valid. Use the parameter to inspect members (a List<ulong> of user IDs) and teamLeader, or to look up the team again with RelationshipManager.ServerInstance.FindTeam. Because the parameter is already typed as RelationshipManager.PlayerTeam, there is no narrower type to declare; every call passes the same concrete object. This hook only intercepts the tool the server uses to remove the team, so it covers both player-initiated disbands and automatic ones. Guard against repeat calls: if you cancel a disband, the game may attempt another disband later on the same team.
Example plugin: Keep a team alive until its members leave
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Team Disband Guard", "RustPluginGenerator", "1.0.0")]
[Description("Prevents protected teams with multiple members from being disbanded")]
public class TeamDisbandGuard : RustPlugin
{
private const string PermProtected = "teamdisbandguard.protected";
private const string PermAdmin = "teamdisbandguard.admin";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastWarn = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Minimum members to protect")]
public int MinimumMembers = 2;
[JsonProperty("Warning cooldown seconds")]
public float WarningCooldown = 10f;
}
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>
{
["DisbandBlocked"] = "Your team cannot be disbanded while it has {0} members. Members must leave individually.",
["ProtectionOn"] = "Team disband protection is now enabled for your team.",
["ProtectionOff"] = "Team disband protection is now disabled for 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(PermProtected, this);
permission.RegisterPermission(PermAdmin, this);
}
private object OnTeamDisband(RelationshipManager.PlayerTeam teamToDisband)
{
if (teamToDisband == null || teamToDisband.members == null) return null;
if (teamToDisband.members.Count < config.MinimumMembers) return null;
bool isProtected = false;
foreach (ulong memberId in teamToDisband.members)
{
if (permission.UserHasPermission(memberId.ToString(), PermProtected))
{
isProtected = true;
break;
}
}
if (!isProtected) return null;
float now = Time.realtimeSinceStartup;
foreach (ulong memberId in teamToDisband.members)
{
if (lastWarn.TryGetValue(memberId, out float last) && now - last < config.WarningCooldown) continue;
lastWarn[memberId] = now;
BasePlayer player = BasePlayer.FindByID(memberId);
if (player == null || !player.IsConnected) continue;
player.ChatMessage(Msg("DisbandBlocked", player.UserIDString, teamToDisband.members.Count));
}
return true;
}
[ChatCommand("teamguard")]
private void CmdTeamGuard(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
{
SendReply(player, "You do not have permission to use this command.");
return;
}
if (permission.UserHasPermission(player.UserIDString, PermProtected))
{
permission.RevokeUserPermission(player.UserIDString, PermProtected);
SendReply(player, Msg("ProtectionOff", player.UserIDString));
}
else
{
permission.GrantUserPermission(player.UserIDString, PermProtected, this);
SendReply(player, Msg("ProtectionOn", player.UserIDString));
}
}
private void Unload()
{
lastWarn.Clear();
}
}
}The plugin protects teams whose disband you want to postpone for a short grace period. OnTeamDisband reads the teams members list and the calling context: teams that still hold at least two players from a protected user group are kept alive and the members are warned in chat. Protected teams are identified by a configurable permission; the check walks teamToDisband.members, converts each ulong to a user ID string and asks the permission system. A short cooldown stored in a Dictionary<ulong, float> prevents the guard from spamming chat when the game retries the disband repeatedly. Admins can toggle protection with a chat command, and the cooldown map is cleared in Unload.
Common use cases
Minimum team size
Cancel the disband while the team still has more than one member that has not been kicked, forcing players to leave individually so you can track departures in OnTeamLeave.
Protected or ranked teams
Refuse to disband teams flagged through your own data file, for example tournament teams or teams that paid an entry fee and must not be destroyed mid-event.
Audit trail
Log every disband attempt with the team ID and member list before allowing it, then correlate the entries with OnTeamDisbanded to see which removals were real.
Pitfalls
Blocking leaves too
The last member leaving a team also triggers DisbandTeam, so a blanket cancel keeps players stuck in an empty-looking team. Only block when members.Count indicates a real disband.
OnTeamDisbanded will not fire
If you return a non-null value, the game skips both the removal and the OnTeamDisbanded hook. Any cleanup you do there must be handled elsewhere.
Distinguish player actions
There is no initiator parameter. To know whether a player pressed the disband button, combine this hook with OnTeamLeave or track client commands, otherwise you cannot tell a leader action from an automatic teardown.
Build a plugin with OnTeamDisband
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 OnTeamDisband
Generate