OnTeamCreated
OnTeamCreated is called right after a new team is created via RelationshipManager.TryCreateTeam, once the leader has been set and added to the team's member list. It fires before any invite or join message flow, so it is the earliest point to react to a brand new team.
void OnTeamCreated(BasePlayer player, RelationshipManager.PlayerTeam playerTeam)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer who triggered team creation. This is the player who ran the create-team action (for example /create) and becomes the team leader. It is a connected player, not a sleeper. |
playerTeam | RelationshipManager.PlayerTeam | The RelationshipManager.PlayerTeam instance that was just created. It already has teamID set, teamLeader equal to player.userID, and the leader added to members, so you can read or change it immediately. |
Return value
The return value is ignored. The original method returns void and continues regardless of what your hook returns, so you cannot prevent or replace team creation from OnTeamCreated. To block or alter creation, use the OnTeamCreate hook instead.
How it works
The hook fires inside RelationshipManager.TryCreateTeam, after a fresh PlayerTeam is allocated from the server instance, the leader is assigned, and the player is added to the team. At that moment the team has exactly one member (the leader) and teamID is already valid. Every game path that creates a team runs through this method, so accepting an invite to a non-existent team or a console/plugin call that builds a team will reach it too, not only the chat command a player types.
Use player for identity and permission checks, and playerTeam for the team data: teamID, teamLeader, and members. You can tag or record the team immediately, seed metadata keyed by teamID, or apply a starting state (for example store the creation time).
Declaring player as BasePlayer matches the game's actual argument; narrowing it to a subclass would make Oxide skip calls where the argument is not that type. Because this is a void game method and the return value is ignored, the hook cannot cancel creation. The team already exists when your code runs, so treat it as a notification, not a guard.
Example plugin: Record new teams and give the leader a welcome notice
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Team Created Logger", "RustPluginGenerator", "1.0.0")]
[Description("Records newly created teams and optionally notifies the team leader.")]
public class TeamCreatedLogger : RustPlugin
{
private const string DataFileName = "TeamCreatedLogger";
private PluginConfig config;
private Dictionary<string, TeamRecord> records = new Dictionary<string, TeamRecord>();
private class PluginConfig
{
[JsonProperty("Notify leader in chat")]
public bool NotifyLeader { get; set; } = true;
[JsonProperty("Maximum stored records")]
public int MaxRecords { get; set; } = 5000;
}
private class TeamRecord
{
[JsonProperty("teamId")]
public ulong TeamId { get; set; }
[JsonProperty("leaderName")]
public string LeaderName { get; set; }
[JsonProperty("leaderSteamId")]
public string LeaderSteamId { get; set; }
[JsonProperty("createdUnix")]
public int CreatedUnix { get; set; }
}
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>
{
["TeamCreated"] = "Your team has been created. Team ID: {0}"
}, this);
}
private string Msg(string key, string userId = null, params object[] args)
{
return string.Format(lang.GetMessage(key, this, userId), args);
}
private void OnServerInitialized()
{
records = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, TeamRecord>>(DataFileName)
?? new Dictionary<string, TeamRecord>();
}
private void OnTeamCreated(BasePlayer player, RelationshipManager.PlayerTeam playerTeam)
{
if (player == null || playerTeam == null) return;
string key = playerTeam.teamID.ToString();
if (records.ContainsKey(key)) return;
if (records.Count >= config.MaxRecords) return;
records[key] = new TeamRecord
{
TeamId = playerTeam.teamID,
LeaderName = player.displayName,
LeaderSteamId = player.UserIDString,
CreatedUnix = Facepunch.Math.Epoch.Current
};
if (config.NotifyLeader && player.IsConnected)
{
player.ChatMessage(Msg("TeamCreated", player.UserIDString, playerTeam.teamID));
}
}
private void OnServerSave()
{
Interface.Oxide.DataFileSystem.WriteObject(DataFileName, records);
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(DataFileName, records);
}
}
}The plugin stores a simple record for each team when it is created: the team ID, leader name, leader Steam ID, a unix timestamp, and a starting member count. Writes go to oxide/data/TeamCreatedLogger through the data file system. Optionally, the leader receives a chat line confirming the team exists and showing the team ID, which is useful on servers that hand out team-based rewards. The config toggles the chat notice and sets the maximum number of stored records so the data file does not grow without bound. Records are saved on unload and also on the server's periodic save hook.
Common use cases
Register team-based reward eligibility
Create a record keyed by
teamIDso later hooks likeOnTeamMemberInviteorOnTeamAcceptInvitecan check whether the team is new and grant a starter bonus.Audit team creation
Log every new team with the leader's Steam ID and time so admins can investigate suspicious team churn or abusive team-splitting on PvP servers.
Apply starting team settings
Initialize per-team metadata such as a friendly-fire flag or a display name, then let players modify it through your own chat commands.
Pitfalls
Cannot cancel creation here
The return value is ignored and the team already exists. If you need to reject team creation, handle the
OnTeamCreatehook instead ofOnTeamCreated.Team has only the leader
Do not assume members beyond the leader are present. Read
playerTeam.membersfresh rather than caching the count and expecting it to stay accurate as players join.Not every creation is a chat command
Other paths and plugins can call team creation directly. Guard against duplicate records by checking that
teamIDis not already stored before writing.
Build a plugin with OnTeamCreated
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 OnTeamCreated
Generate