OnClanColorChanged
OnClanColorChanged is called after a clan's color has been written to the database and the clan has already been marked as changed.
void OnClanColorChanged(LocalClan localClan, UnityEngine.Color32 newColor, ulong bySteamId)Parameters
| Parameter | Type | Description |
|---|---|---|
localClan | LocalClan | The LocalClan whose color was just changed. Use it to read ClanId, name, members or the stored color via the clan backend. |
newColor | UnityEngine.Color32 | The new clan color as a UnityEngine.Color32. Convert with newColor.ToHex() or read the r/g/b/a fields directly. |
bySteamId | ulong | Steam ID (ulong) of the player who performed the color change, as recorded in the clan log entry. |
Return value
The call site ignores the return value, and the original method returns void. Returning null, true, false or nothing has no effect on the color change or the resulting ClanResult.Success.
How it works
The hook fires inside LocalClan.SetColor only on the success path: the backend's UpdateClanColor returned true, a set_color entry was appended to the clan log with the actor's Steam ID, and localClan.Changed(ClanDataSource.Basic) has already run to broadcast the update to clients. In practice this means the color change is committed when your hook runs; there is no cancel state to work with here.
localClan is the live LocalClan instance, so you can read its ID, name and member list. newColor is the value that was just stored, useful for building a chat announcement or a Discord message with a hex swatch. bySteamId identifies who made the change, which lets you attribute the log line or apply permission-based restrictions.
The injected call does not pass a color to any override, so declaring a narrower parameter type for localClan (for example LocalClan subclasses) is not useful here; the argument is always a LocalClan. Keep the handler fast: color changes are rare, but the clan backend may still be busy writing to its database.
Example plugin: Announce clan color changes in chat
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Clan Color Announcer", "RustPluginGenerator", "1.0.0")]
[Description("Announces clan color changes in global chat and to the clan's members")]
public class ClanColorAnnouncer : RustPlugin
{
private const string PermAdmin = "clancolorannouncer.admin";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Announce globally")]
public bool AnnounceGlobally { get; set; } = true;
[JsonProperty("Notify clan members")]
public bool NotifyClanMembers { get; set; } = true;
[JsonProperty("Show actor Steam ID")]
public bool ShowActorId { 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>
{
["Global"] = "{0} changed their clan color to #{1}.",
["Clan"] = "{0} changed the clan color to #{1}.",
["ActorUnknown"] = "a member",
["ActorId"] = "{0}x",
["ClanNameFallback"] = "Clan #{0}"
}, 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(PermAdmin, this);
}
private void OnClanColorChanged(LocalClan localClan, Color32 newColor, ulong bySteamId)
{
if (localClan == null) return;
string hex = newColor.ToHex();
string actorId = bySteamId.ToString();
string actorName = ResolveName(actorId);
string clanName = ResolveClanName(localClan);
if (config.AnnounceGlobally)
{
Server.Broadcast(Msg("Global", null, clanName, hex));
}
if (config.NotifyClanMembers)
{
string line = Msg("Clan", null, actorName, hex);
foreach (var basePlayer in BasePlayer.activePlayerList)
{
if (basePlayer == null) continue;
if (IsClanMember(localClan, basePlayer.userID.Get()))
{
basePlayer.ChatMessage(line);
}
}
}
if (config.ShowActorId)
{
Puts(string.Format("Clan {0} ({1}) color set to #{2} by {3}", clanName, localClan.ClanId, hex, actorId));
}
}
private bool IsClanMember(LocalClan clan, ulong userId)
{
try
{
foreach (var member in clan.Members)
{
if (member.SteamId == userId) return true;
}
}
catch
{
}
return false;
}
private string ResolveName(string userId)
{
var player = BasePlayer.FindAwakeOrSleeping(userId);
return player != null ? player.displayName : Msg("ActorUnknown");
}
private string ResolveClanName(LocalClan clan)
{
try
{
if (!string.IsNullOrEmpty(clan.Name)) return clan.Name;
}
catch
{
}
return Msg("ClanNameFallback", null, clan.ClanId);
}
}
}The plugin registers a hook that runs whenever a clan's color changes, receiving the LocalClan, the new Color32, and the Steam ID of the actor. It resolves the clan name from localClan (falling back to Clan #{ClanId}), formats the color with newColor.ToHex(), and, if AnnounceGlobally is enabled, broadcasts a message to all players. When NotifyClanMembers is enabled, it sends a separate chat line to each online member of the clan so they see the change. All text lives in the language file. Three config toggles control the global broadcast, the clan-member notification, and whether the actor's Steam ID is written to the server log via ShowActorId.
Common use cases
Audit trail for clan branding
Write a line to oxide/data recording clan ID, new hex color, actor Steam ID and a UTC timestamp so admins can trace griefing or impersonation attempts.
Global or team-scoped notification
Broadcast the change to everyone or only to the clan's members, including the actor's display name looked up from SteamID.
Cosmetic integration
Store the last known color per clan and reuse it as the accent color when rendering your own clan UI, scoreboard or chat prefix.
Pitfalls
The change already succeeded
By the time the hook runs, the database row is updated and
Changedhas been broadcast. Returning anything cannot block or revert it; you would need to call the clan color API again yourself.No automatic permission check
The hook fires regardless of who made the request. If you want to restrict color changes to leaders or officers, enforce that yourself using
bySteamIdand the clan member data.Null localClan is unlikely but cheap to guard
The backend always passes the instance, but a null check costs nothing and protects against future signature or plugin-call differences.
Build a plugin with OnClanColorChanged
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 OnClanColorChanged
Generate