C#:
// ╔═══════════════════════════════════════════════════════════════════════════╗
// ║
// ║ Plugin : PlayerTeam
// ║ Author : WuyZar
// ║ Discord : https://discord.gg/NVwRcQwGwh
// ║ Shop : https://codefling.com/wuyzar
// ║
// ║ All rights reserved. Redistribution and modification are forbidden !
// ║
// ╚═══════════════════════════════════════════════════════════════════════════╝
using System; using System.Collections.Generic; using Oxide.Core; using Oxide.Core.Libraries.Covalence; using Oxide.Core.Plugins; using Oxide.Game.Rust.Cui; using UnityEngine;
namespace Oxide.Plugins
{
[Info("PlayerTeam", "WuyZar", "1.0.0")]
[Description("Discord: https://discord.gg/NVwRcQwGwh")]
public class PlayerTeam : RustPlugin
{
#region Config
private PluginConfig config;
private class PluginConfig
{
public string ClanTagColor { get; set; } = "#6FA8D6";
}
protected override void LoadDefaultConfig() { config = new PluginConfig(); SaveConfig(); }
protected override void SaveConfig() => Config.WriteObject(config, true);
protected override void LoadConfig() { base.LoadConfig(); config = Config.ReadObject<PluginConfig>() ?? new PluginConfig(); }
#endregion
#region Fields
[PluginReference] private Plugin BetterChat;
private PluginData data;
private HashSet<ulong> awaitingCreation = new();
private Dictionary<ulong, string> pendingInput = new();
private const string UIBg = "PlayerTeam_Bg";
private const string UIMain = "PlayerTeam_Main";
private const string UIBox = "PlayerTeam_Box";
private const int NameMaxLength = 15;
private class ClanInfo
{
public string Name { get; set; } = "";
public List<ulong> Members { get; set; } = new();
}
private class PluginData
{
public Dictionary<ulong, ClanInfo> TeamClans { get; set; } = new();
}
#endregion
#region Oxide Hooks
private void Init() => LoadData();
private void OnServerInitialized() => RegisterWithBetterChat();
private void OnPluginLoaded(Plugin plugin) { if (plugin.Name == "BetterChat") RegisterWithBetterChat(); }
private void Unload() { foreach (var player in BasePlayer.activePlayerList) CloseUI(player); }
private void OnTeamCreated(BasePlayer player, RelationshipManager.PlayerTeam team)
{
if (player == null || team == null) return;
awaitingCreation.Add(player.userID);
pendingInput[player.userID] = string.Empty;
OpenUI(player, true, "");
}
private void OnTeamLeave(RelationshipManager.PlayerTeam currentTeam, BasePlayer player)
{
if (currentTeam == null || player == null) return;
ClanInfo clan;
if (!data.TeamClans.TryGetValue(currentTeam.teamID, out clan)) return;
if (player.userID != currentTeam.teamLeader)
{
clan.Members.Remove(player.userID);
SaveData();
return;
}
data.TeamClans.Remove(currentTeam.teamID);
SaveData();
awaitingCreation.Remove(player.userID);
pendingInput.Remove(player.userID);
OpenUI(player, false, "You deleted your team.");
var remainingMembers = new List<ulong>(currentTeam.members);
remainingMembers.Remove(player.userID);
foreach (var memberId in remainingMembers)
{
var member = BasePlayer.FindByID(memberId);
if (member != null) member.ChatMessage($"<color=#E8736A>PlayerTeam</color> <color=#1A1C22>»</color> The clan <color={config.ClanTagColor}>{clan.Name}</color> was disbanded because the leader left the team.");
}
foreach (var memberId in remainingMembers)
{
currentTeam.RemovePlayer(memberId);
}
}
private void OnTeamAcceptInvite(RelationshipManager.PlayerTeam team, BasePlayer player)
{
if (team == null || player == null) return;
ClanInfo clan;
if (!data.TeamClans.TryGetValue(team.teamID, out clan)) return;
if (!clan.Members.Contains(player.userID))
{
clan.Members.Add(player.userID);
SaveData();
}
}
private void OnTeamKick(RelationshipManager.PlayerTeam currentTeam, BasePlayer player, ulong target)
{
if (currentTeam == null) return;
ClanInfo clan;
if (!data.TeamClans.TryGetValue(currentTeam.teamID, out clan)) return;
clan.Members.Remove(target);
SaveData();
}
#endregion
#region BetterChat
private void RegisterWithBetterChat() => BetterChat?.Call("API_RegisterThirdPartyTitle", this, (Func<IPlayer, string>)GetClanTitle);
private string GetClanTitle(IPlayer player)
{
var basePlayer = player?.Object as BasePlayer;
if (basePlayer == null) return null;
var team = basePlayer.Team;
if (team == null) return null;
ClanInfo clan;
if (!data.TeamClans.TryGetValue(team.teamID, out clan)) return null;
return $"[#{config.ClanTagColor.TrimStart('#')}][+15][{clan.Name}][/+][/#]";
}
#endregion
#region Commands
[ConsoleCommand("clanui.input")]
private void CmdClanInput(ConsoleSystem.Arg arg)
{
var player = arg.Player();
if (player == null) return;
pendingInput[player.userID] = arg.GetString(0, string.Empty);
}
[ConsoleCommand("clanui.close")]
private void CmdClanClose(ConsoleSystem.Arg arg)
{
var player = arg.Player();
if (player == null) return;
if (!awaitingCreation.Contains(player.userID)) { CloseUI(player); return; }
string rawName;
pendingInput.TryGetValue(player.userID, out rawName);
string name = SanitizeClanName(rawName);
if (string.IsNullOrEmpty(name)) { FlashBox(player); return; }
awaitingCreation.Remove(player.userID);
pendingInput.Remove(player.userID);
CloseUI(player);
var team = player.Team;
if (team == null) return;
data.TeamClans[team.teamID] = new ClanInfo { Name = name, Members = new List<ulong>(team.members) };
SaveData();
player.ChatMessage($"<color=#E8736A>PlayerTeam</color> <color=#1A1C22>»</color> Your clan is now named <color={config.ClanTagColor}>{name}</color>.");
}
#endregion
#region UI
private void OpenUI(BasePlayer player, bool editable, string infoMessage)
{
CloseUI(player);
var elements = new CuiElementContainer();
elements.Add(new CuiButton
{
Button = { Command = "clanui.close", Color = "0 0 0 0.8", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat" },
Text = { Text = "" },
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }
}, "Overlay", UIBg);
elements.Add(new CuiElement { Name = UIMain, Parent = "Overlay", Components = {
new CuiImageComponent { Color = "0.102 0.110 0.133 1.00" },
new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-120 0", OffsetMax = "120 90" },
new CuiNeedsCursorComponent()
}});
elements.Add(new CuiElement { Name = "PlayerTeam_Title", Parent = UIMain, Components = {
new CuiTextComponent { Text = editable ? "CREATE A TEAM" : "DELETE TEAM", FontSize = 15, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1" },
new CuiRectTransformComponent { AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-110 -30", OffsetMax = "30 -5" }
}});
elements.Add(new CuiElement { Name = "PlayerTeam_Sep", Parent = UIMain, Components = {
new CuiImageComponent { Color = "1.000 1.000 1.000 1.00" },
new CuiRectTransformComponent { AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-110 -37", OffsetMax = "110 -35" }
}});
elements.Add(new CuiElement { Name = UIBox, Parent = UIMain, Components = {
new CuiImageComponent { Color = editable ? "0.435 0.659 0.839 0.50" : "0.910 0.451 0.416 0.50" },
new CuiRectTransformComponent { AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-110 -65", OffsetMax = "110 -45" }
}});
if (editable)
{
elements.Add(new CuiElement { Parent = UIBox, Components = {
new CuiInputFieldComponent { Text = "", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "0.435 0.659 0.839 1.00", CharsLimit = NameMaxLength, Command = "clanui.input", NeedsKeyboard = true },
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}});
}
else
{
elements.Add(new CuiElement { Parent = UIBox, Components = {
new CuiTextComponent { Text = infoMessage, FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "0.910 0.451 0.416 1.00" },
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}});
}
elements.Add(new CuiElement { Name = "PlayerTeam_Hint", Parent = UIMain, Components = {
new CuiTextComponent { Text = editable ? "Type, then click outside to confirm." : "Click outside to close.", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0.353 0.369 0.416 1.00" },
new CuiRectTransformComponent { AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-110 -85", OffsetMax = "110 -70" }
}});
CuiHelper.AddUi(player, elements);
}
private void CloseUI(BasePlayer player)
{
CuiHelper.DestroyUi(player, UIBg);
CuiHelper.DestroyUi(player, UIMain);
}
private void FlashBox(BasePlayer player)
{
var flash = new CuiElementContainer();
flash.Add(new CuiElement { Name = "PlayerTeam_Flash", Parent = UIMain, Components = {
new CuiImageComponent { Color = "0.910 0.451 0.416 0.9" },
new CuiRectTransformComponent { AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-110 -65", OffsetMax = "110 -45" }
}});
CuiHelper.AddUi(player, flash);
timer.Once(0.1f, () => { if (player != null && player.IsConnected) CuiHelper.DestroyUi(player, "PlayerTeam_Flash"); });
}
#endregion
#region Helpers
private string SanitizeClanName(string input)
{
if (string.IsNullOrWhiteSpace(input)) return string.Empty;
string cleaned = input.Trim().Replace("<", "").Replace(">", "");
if (cleaned.Length > NameMaxLength) cleaned = cleaned.Substring(0, NameMaxLength);
return cleaned;
}
#endregion
#region Data
private void LoadData()
{
try { data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>(Name); }
catch { data = new PluginData(); }
if (data == null) data = new PluginData();
if (data.TeamClans == null) data.TeamClans = new Dictionary<ulong, ClanInfo>();
}
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, data);
#endregion
}
}