C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using ConVar;
using CompanionServer;
using Oxide.Core.Libraries.Covalence;
// ____ _ _ _
// / ___|(_) __ _(_) | ___
// \___ \| |/ _` | | |/ _ \
// ___) | | (_| | | | (_) |
// |____/|_|\__, |_|_|\___/
// |___/
// ☽✧✵✧✵✧✵✧✵✧✵✧✵✧☾
// ✦ RUST PLUGINS ✦
// ✦ Sigilo.dev ✦
// ☽✧✵✧✵✧✵✧✵✧✵✧✵✧☾
namespace Oxide.Plugins
{
[Info("Name Color", "Sigilo", "1.0.0")]
[Description("Visual name color picker with solid colors, gradients and patterns")]
public class NameColor : RustPlugin
{
[PluginReference] private Plugin BetterChat;
private const string PermUse = "namecolor.use";
private const string PermGradient = "namecolor.gradient";
private const string PermPattern = "namecolor.pattern";
private const string LayerBase = "NameColor_Base";
private const string LayerContent = "NameColor_Content";
private Configuration _config;
private StoredData _data;
private readonly StringBuilder _sb = new StringBuilder();
#region Configuration
private class Configuration
{
[JsonProperty("Solid Colors")]
public List<ColorPreset> SolidColors { get; set; } = new List<ColorPreset>
{
// Grayscales (10)
new ColorPreset("#000000", "True Black"), new ColorPreset("#1A1A1A", "Deep Gray"),
new ColorPreset("#2D3436", "Charcoal"), new ColorPreset("#404040", "Dark Gray"),
new ColorPreset("#636E72", "Slate"), new ColorPreset("#808080", "Gray"),
new ColorPreset("#B2BEC3", "Silver"), new ColorPreset("#D3D3D3", "Light Gray"),
new ColorPreset("#E5E5E5", "Cloud"), new ColorPreset("#FFFFFF", "True White"),
// Reds (10)
new ColorPreset("#4A0000", "Night Red"), new ColorPreset("#8B0000", "Dark Red"),
new ColorPreset("#A52A2A", "Brownish Red"), new ColorPreset("#C0392B", "Strong Red"),
new ColorPreset("#D63031", "Chi-Gon Red"), new ColorPreset("#E74C3C", "Alizarin"),
new ColorPreset("#FF0000", "Pure Red"), new ColorPreset("#FF4757", "Cherry"),
new ColorPreset("#FF6B6B", "Pastel Red"), new ColorPreset("#FFB8B8", "Soft Red"),
// Oranges (10)
new ColorPreset("#803E00", "Deep Burnt"), new ColorPreset("#A0522D", "Sienna"),
new ColorPreset("#D35400", "Pumpkin"), new ColorPreset("#E17055", "Terra"),
new ColorPreset("#E67E22", "Carrot"), new ColorPreset("#F39C12", "Orange"),
new ColorPreset("#FA8231", "Vivid Orange"), new ColorPreset("#FF8E53", "Sunset"),
new ColorPreset("#FAB1A0", "Peach Orange"), new ColorPreset("#FFE0D0", "Skin"),
// Yellows/Gold (10)
new ColorPreset("#B8860B", "Dark Gold"), new ColorPreset("#DAA520", "Goldenrod"),
new ColorPreset("#EAB543", "Mustard"), new ColorPreset("#F1C40F", "Yellow"),
new ColorPreset("#FFD93D", "Gold"), new ColorPreset("#F9CA24", "Sunglow"),
new ColorPreset("#FFE66D", "Pastel Yellow"), new ColorPreset("#FFFACD", "Lemon Chiffon"),
new ColorPreset("#F8EFBA", "Cream"), new ColorPreset("#FFFFF0", "Ivory"),
// Greens (10)
new ColorPreset("#1B3022", "Deep Forest"), new ColorPreset("#27AE60", "Nephritis"),
new ColorPreset("#2ED573", "Emerald"), new ColorPreset("#009432", "Green"),
new ColorPreset("#26DE81", "Dragon Green"), new ColorPreset("#BADC58", "Lime"),
new ColorPreset("#6BCB77", "Mint"), new ColorPreset("#A3CB38", "Olive Green"),
new ColorPreset("#78E08F", "Aurora Green"), new ColorPreset("#D1F2EB", "Pale Green"),
// Teals/Cyans (10)
new ColorPreset("#006266", "Deep Teal"), new ColorPreset("#16A085", "Teal"),
new ColorPreset("#009688", "Dark Cyan"), new ColorPreset("#00B894", "Jade"),
new ColorPreset("#00CEC9", "Turquoise"), new ColorPreset("#00D2D3", "Cyan"),
new ColorPreset("#48DBFB", "Neon Blue"), new ColorPreset("#55EFC4", "Aqua"),
new ColorPreset("#81ECEC", "Faded Cyan"), new ColorPreset("#E0FFFF", "Mist"),
// Blues (10)
new ColorPreset("#0A192F", "Night Blue"), new ColorPreset("#192A56", "Midnight"),
new ColorPreset("#2980B9", "Navy"), new ColorPreset("#0984E3", "Blue"),
new ColorPreset("#1E90FF", "Dodger Blue"), new ColorPreset("#4D96FF", "Sky"),
new ColorPreset("#74B9FF", "Ice"), new ColorPreset("#3BF6FF", "Electric Blue"),
new ColorPreset("#25CCF7", "Light Blue"), new ColorPreset("#E3F2FD", "Soft Blue"),
// Purples (10)
new ColorPreset("#2D033B", "Deep Violet"), new ColorPreset("#4834D4", "Deep Purple"),
new ColorPreset("#4B0082", "Indigo"), new ColorPreset("#6C5CE7", "Exotic Blue"),
new ColorPreset("#8E44AD", "Wisteria"), new ColorPreset("#9B59B6", "Amethyst"),
new ColorPreset("#A29BFE", "Lavender"), new ColorPreset("#D6A2E8", "Lilac"),
new ColorPreset("#BE90D4", "Light Purple"), new ColorPreset("#F3E5F5", "Orchid"),
// Pinks (10)
new ColorPreset("#6D214F", "Plum"), new ColorPreset("#833471", "Berry"),
new ColorPreset("#B33771", "Fuchsia"), new ColorPreset("#D81B60", "Ruby"),
new ColorPreset("#E84393", "Magenta"), new ColorPreset("#E056FD", "Neon Pink"),
new ColorPreset("#FD79A8", "Rose"), new ColorPreset("#FDA7DF", "Pink"),
new ColorPreset("#FF9FF3", "Jigglypuff"), new ColorPreset("#FFDEF2", "Fairy"),
// Browns/Earth (10)
new ColorPreset("#3E2723", "Ebony"), new ColorPreset("#5D4037", "Coffee"),
new ColorPreset("#795548", "Brown"), new ColorPreset("#8D6E63", "Clay"),
new ColorPreset("#A1887F", "Tan"), new ColorPreset("#706FD3", "Slate Blue"),
new ColorPreset("#58B19F", "Sage"), new ColorPreset("#D2B48C", "Tan Leather"),
new ColorPreset("#FEA47F", "Peach"), new ColorPreset("#FFF5E1", "Shell")
};
[JsonProperty("Gradients")]
public List<GradientPreset> Gradients { get; set; } = new List<GradientPreset>
{
new GradientPreset("Sunset", new[] { "#FF6B6B", "#FFD93D" }),
new GradientPreset("Ocean", new[] { "#667eea", "#764ba2" }),
new GradientPreset("Aurora", new[] { "#00D2D3", "#6BCB77", "#FFD93D" }),
new GradientPreset("Fire", new[] { "#FF4757", "#FFA502", "#FFD93D" }),
new GradientPreset("Ice", new[] { "#74B9FF", "#A29BFE", "#DFE6E9" }),
new GradientPreset("Neon", new[] { "#E056FD", "#00D2D3" }),
new GradientPreset("Forest", new[] { "#2ED573", "#00B894", "#006266" }),
new GradientPreset("Galaxy", new[] { "#9B59B6", "#E056FD", "#4D96FF" }),
new GradientPreset("Blood", new[] { "#8B0000", "#FF4757", "#FF6B6B" }),
new GradientPreset("Midnight", new[] { "#000000", "#1E90FF" }),
new GradientPreset("Lava", new[] { "#FFD700", "#FF4500", "#000000" }),
new GradientPreset("Tropical", new[] { "#00FF00", "#FFFF00", "#FF7F00" }),
new GradientPreset("Berry", new[] { "#8E44AD", "#E84393", "#FF4757" }),
new GradientPreset("Clouds", new[] { "#1E90FF", "#FFFFFF" }),
new GradientPreset("Dusk", new[] { "#4B0082", "#FF7F00" }),
new GradientPreset("Metal", new[] { "#BDC3C7", "#2C3E50" }),
new GradientPreset("Candy", new[] { "#FF69B4", "#00FFFF" }),
new GradientPreset("Inferno", new[] { "#8B0000", "#FF0000", "#FFFF00" }),
new GradientPreset("Sunrise", new[] { "#FAD961", "#F76B1C" }),
new GradientPreset("Deep Sea", new[] { "#2C3E50", "#4CA1AF" }),
new GradientPreset("Grape", new[] { "#E056FD", "#686DE0" }),
new GradientPreset("Peach", new[] { "#FF9A9E", "#FECFEF" }),
new GradientPreset("Minty", new[] { "#00B894", "#81ECEC" }),
new GradientPreset("Cocoa", new[] { "#6D214F", "#2C3A47" }),
new GradientPreset("Alien", new[] { "#786fa6", "#55EFC4" }),
new GradientPreset("Retro", new[] { "#3BF6FF", "#FF00FF", "#FFFF00" }),
new GradientPreset("Emerald City", new[] { "#009432", "#A3CB38" }),
new GradientPreset("Flamingo", new[] { "#f78fb3", "#cf6a87" }),
new GradientPreset("Space", new[] { "#000000", "#9B59B6", "#2980B9" }),
new GradientPreset("Royal", new[] { "#F1C40F", "#8E44AD" }),
new GradientPreset("Copper", new[] { "#D35400", "#E67E22", "#F1C40F" }),
new GradientPreset("Silver", new[] { "#2C3E50", "#ECF0F1" }),
new GradientPreset("Golden Hour", new[] { "#F39C12", "#D35400", "#C0392B" }),
new GradientPreset("Twilight", new[] { "#2C3E50", "#8E44AD", "#E17055" }),
new GradientPreset("Spring", new[] { "#FDA7DF", "#BADC58", "#F9CA24" }),
new GradientPreset("Autumn", new[] { "#D35400", "#E17055", "#636E72" }),
new GradientPreset("Winter", new[] { "#FFFFFF", "#74B9FF", "#81ECEC" })
};
[JsonProperty("Patterns")]
public List<PatternPreset> Patterns { get; set; } = new List<PatternPreset>
{
new PatternPreset("Rainbow", new[] { "#FF0000", "#FF7F00", "#FFFF00", "#00FF00", "#0000FF", "#4B0082", "#9400D3" }),
new PatternPreset("Candy Cane", new[] { "#FF0000", "#FFFFFF" }),
new PatternPreset("Bumblebee", new[] { "#FFD700", "#000000" }),
new PatternPreset("Police", new[] { "#0000FF", "#FF0000" }),
new PatternPreset("Zebra", new[] { "#FFFFFF", "#000000" }),
new PatternPreset("Watermelon", new[] { "#FF6B6B", "#2ED573" }),
new PatternPreset("Christmas", new[] { "#FF0000", "#008000" }),
new PatternPreset("Halloween", new[] { "#FF7518", "#000000" }),
new PatternPreset("Matrix", new[] { "#000000", "#00FF00" }),
new PatternPreset("Traffic Light", new[] { "#FF0000", "#FFFF00", "#00FF00" }),
new PatternPreset("USA", new[] { "#FF0000", "#FFFFFF", "#0000FF" }),
new PatternPreset("Germany", new[] { "#000000", "#FF0000", "#FFCC00" }),
new PatternPreset("France", new[] { "#0000FF", "#FFFFFF", "#FF0000" }),
new PatternPreset("Italy", new[] { "#008000", "#FFFFFF", "#FF0000" }),
new PatternPreset("Camo", new[] { "#2F361F", "#4B5320", "#8F9779", "#000000" }),
new PatternPreset("Pastel", new[] { "#FF9FF3", "#54A0FF", "#FECA57", "#5F27CD" }),
new PatternPreset("Neon City", new[] { "#8E44AD", "#00D2D3", "#FF9FF3" }),
new PatternPreset("Brazil", new[] { "#009c3b", "#ffdf00", "#002776" }),
new PatternPreset("Sweden", new[] { "#006AA7", "#FECC00" }),
new PatternPreset("Ukraine", new[] { "#0057B8", "#FFD700" }),
// New additions
new PatternPreset("Argentina", new[] { "#75AADB", "#FFFFFF", "#75AADB" }),
new PatternPreset("Chile", new[] { "#D52B1E", "#FFFFFF", "#0039A6" }),
new PatternPreset("Peru", new[] { "#D91023", "#FFFFFF", "#D91023" }),
new PatternPreset("Colombia", new[] { "#FCD116", "#003893", "#CE1126" }),
new PatternPreset("Mexico", new[] { "#006847", "#FFFFFF", "#CE1126" }),
new PatternPreset("Paraguay", new[] { "#D52B1E", "#FFFFFF", "#0038A8" }),
new PatternPreset("Bolivia", new[] { "#D52B1E", "#FCD116", "#007934" }),
new PatternPreset("Uruguay", new[] { "#0038A8", "#FFFFFF" }),
new PatternPreset("Venezuela", new[] { "#FCD116", "#00247D", "#CF142B" })
};
[JsonProperty("Colors Per Row")]
public int ColorsPerRow { get; set; } = 6;
[JsonProperty("Data Cleanup Days")]
public int CleanupDays { get; set; } = 30;
}
private class ColorPreset { public string Hex, Name; public ColorPreset(string h, string n) { Hex = h; Name = n; } public ColorPreset() {} }
private class GradientPreset { public string Name; public string[] Colors; public GradientPreset(string n, string[] c) { Name = n; Colors = c; } public GradientPreset() {} }
private class PatternPreset { public string Name; public string[] Colors; public PatternPreset(string n, string[] c) { Name = n; Colors = c; } public PatternPreset() {} }
protected override void LoadDefaultConfig() => _config = new Configuration();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>() ?? new Configuration();
if (_config.Gradients != null) _config.Gradients = _config.Gradients.GroupBy(x => x.Name).Select(x => x.First()).ToList();
if (_config.Patterns != null) _config.Patterns = _config.Patterns.GroupBy(x => x.Name).Select(x => x.First()).ToList();
if (_config.SolidColors != null) _config.SolidColors = _config.SolidColors.GroupBy(x => x.Name).Select(x => x.First()).ToList();
}
catch { LoadDefaultConfig(); }
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(_config);
#endregion
#region Data
private class StoredData { public Dictionary<string, PlayerColorData> Players = new Dictionary<string, PlayerColorData>(); }
private class PlayerColorData
{
public int Type;
public string Val;
public string[] Colors;
public long Last;
}
private enum ColorType { None = 0, Solid = 1, Gradient = 2, Pattern = 3 }
private void LoadData() => _data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name) ?? new StoredData();
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, _data);
#endregion
#region Init/Unload
private void Init()
{
permission.RegisterPermission(PermUse, this);
permission.RegisterPermission(PermGradient, this);
permission.RegisterPermission(PermPattern, this);
LoadData();
}
private void Unload()
{
SaveData();
foreach (var player in BasePlayer.activePlayerList)
{
CuiHelper.DestroyUi(player, LayerContent);
CuiHelper.DestroyUi(player, LayerBase);
}
}
private void OnServerSave() => SaveData();
private void OnPlayerConnected(BasePlayer player)
{
if (_data.Players.TryGetValue(player.UserIDString, out var data))
data.Last = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
#endregion
#region Chat Hook
private object OnPlayerChat(BasePlayer player, string message, Chat.ChatChannel channel)
{
if (BetterChat != null) return null;
if (player == null) return null;
if (!permission.UserHasPermission(player.UserIDString, PermUse)) return null;
if (!_data.Players.TryGetValue(player.UserIDString, out var cData) || cData.Type == 0) return null;
if (cData.Type == (int)ColorType.Gradient && !permission.UserHasPermission(player.UserIDString, PermGradient)) return null;
if (cData.Type == (int)ColorType.Pattern && !permission.UserHasPermission(player.UserIDString, PermPattern)) return null;
var fmtName = FormatName(player.displayName, cData);
var primeColor = (cData.Colors != null && cData.Colors.Length > 0) ? cData.Colors[0] : (cData.Val ?? "#5AF");
if (Chat.serverlog) ServerConsole.PrintColoured($"[{channel}] {player.displayName}: {message}", ConsoleColor.DarkYellow);
switch (channel)
{
case Chat.ChatChannel.Global:
case Chat.ChatChannel.Local:
ConsoleNetwork.BroadcastToAllClients("chat.add2", (int)channel, player.userID, message, fmtName, primeColor);
break;
case Chat.ChatChannel.Team:
if (player.Team != null)
{
if (player.Team.members.Contains(player.userID))
player.Team.BroadcastTeamChat(player.userID, player.displayName, message, primeColor);
var conns = player.Team.GetOnlineMemberConnections();
if (conns != null) ConsoleNetwork.SendClientCommand(conns, "chat.add2", (int)channel, player.userID, message, fmtName, primeColor);
}
else
player.SendConsoleCommand("chat.add2", (int)channel, player.userID, message, fmtName, primeColor);
break;
default:
break;
}
Facepunch.RCon.Broadcast(Facepunch.RCon.LogType.Chat, new Chat.ChatEntry {
Channel = channel, Message = message, UserId = player.UserIDString, Username = player.displayName, Color = primeColor, Time = Facepunch.Math.Epoch.Current
});
return true;
}
private object OnBetterChat(Dictionary<string, object> data)
{
if (!_data.Players.Any()) return null;
var player = data["Player"] as IPlayer;
if (player == null) return null;
if (!permission.UserHasPermission(player.Id, PermUse)) return null;
if (_data.Players.TryGetValue(player.Id, out var cData) && cData.Type != 0)
{
if (cData.Type == (int)ColorType.Gradient && !permission.UserHasPermission(player.Id, PermGradient)) return null;
if (cData.Type == (int)ColorType.Pattern && !permission.UserHasPermission(player.Id, PermPattern)) return null;
string originalName = player.Name;
if (data.ContainsKey("Username")) originalName = data["Username"] as string;
string newName = FormatName(originalName, cData);
data["Username"] = newName;
}
return data;
}
#endregion
#region Logic
private string FormatName(string name, PlayerColorData data)
{
if (data == null) return name;
if (data.Type == (int)ColorType.Solid) return $"<color={data.Val}>{name}</color>";
if (data.Colors == null || data.Colors.Length == 0) return name;
return data.Type == (int)ColorType.Gradient
? ApplyGradient(name, data.Colors)
: ApplyPattern(name, data.Colors);
}
private string ApplyGradient(string name, string[] colors)
{
if (colors.Length < 2) return name;
_sb.Clear();
var len = name.Length;
var list = new List<Color>(len);
var segments = colors.Length - 1;
for (int i = 0; i < len; i++)
{
float t = (len <= 1) ? 0f : (float)i / (len - 1);
float segT = t * segments;
int idx = (int)segT;
if (idx >= segments) idx = segments - 1;
float param = segT - idx;
ColorUtility.TryParseHtmlString(colors[idx], out var c1);
ColorUtility.TryParseHtmlString(colors[idx + 1], out var c2);
list.Add(Color.Lerp(c1, c2, param));
}
for (int i=0; i<len; i++)
_sb.Append($"<color=#{ColorUtility.ToHtmlStringRGB(list[i])}>{name[i]}</color>");
return _sb.ToString();
}
private string ApplyPattern(string name, string[] colors)
{
if (colors.Length == 0) return name;
_sb.Clear();
for (int i = 0; i < name.Length; i++)
_sb.Append($"<color={colors[i % colors.Length]}>{name[i]}</color>");
return _sb.ToString();
}
private string HexToCui(string hex, float alpha = 1.0f)
{
if (string.IsNullOrEmpty(hex)) return "1 1 1 1";
if (ColorUtility.TryParseHtmlString(hex, out var c))
return $"{c.r} {c.g} {c.b} {alpha}";
return "1 1 1 1";
}
#endregion
#region UI Construction
[ChatCommand("color")]
private void ChatCmdGUI(BasePlayer player, string cmd, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, PermUse)) {
SendReply(player, "<color=#FF6B6B>No permission.</color>");
return;
}
OpenBaseUI(player);
UpdateContentUI(player, 0, 0);
}
private void OpenBaseUI(BasePlayer player)
{
CuiHelper.DestroyUi(player, LayerBase);
CuiHelper.DestroyUi(player, LayerContent);
var elements = new CuiElementContainer();
float xMin = 0.01f;
float yMin = 0.1f;
float xMax = 0.32f;
float yMax = 0.75f;
elements.Add(new CuiPanel {
Image = { Color = "0.0 0.0 0.0 0.0", Material = "assets/content/ui/uibackgroundblur.mat" },
RectTransform = { AnchorMin = $"{xMin} {yMin}", AnchorMax = $"{xMax} {yMax}" },
CursorEnabled = true
}, "Overlay", LayerBase);
elements.Add(new CuiPanel {
Image = { Color = "0.1 0.1 0.12 0.98" },
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }
}, LayerBase);
var headerH = 0.08f;
var header = elements.Add(new CuiPanel { Image = { Color = "0.15 0.15 0.2 1" }, RectTransform = { AnchorMin = $"0 {1.0f-headerH}", AnchorMax = "1 1" } }, LayerBase);
elements.Add(new CuiLabel {
Text = { Text = "NAME COLOR", Font = "robotocondensed-bold.ttf", FontSize = 14, Align = TextAnchor.MiddleLeft, Color = "0.8 0.8 0.8 1" },
RectTransform = { AnchorMin = "0.05 0", AnchorMax = "1 1" }
}, header);
elements.Add(new CuiButton {
Button = { Color = "0.8 0.2 0.2 1", Command = "namecolor.close" },
RectTransform = { AnchorMin = "0.88 0.1", AnchorMax = "0.98 0.9" },
Text = { Text = "X", Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
}, header);
CuiHelper.AddUi(player, elements);
}
private void UpdateContentUI(BasePlayer player, int tabIndex, int pageIndex)
{
CuiHelper.DestroyUi(player, LayerContent);
var elements = new CuiElementContainer();
var headerH = 0.08f;
var contentRoot = elements.Add(new CuiPanel {
Image = { Color = "0 0 0 0" },
RectTransform = { AnchorMin = "0 0", AnchorMax = $"1 {1.0f-headerH}" }
}, LayerBase, LayerContent);
float relTabH = 0.07f;
float relTabY = 1.0f - relTabH;
DrawTabs(elements, tabIndex, relTabY, relTabH, player, contentRoot);
float relFooterH = 0.09f;
float contentTop = relTabY - 0.02f;
float contentBot = relFooterH + 0.02f;
int totalPages = 1;
if (tabIndex == 0) totalPages = DrawSolids(elements, pageIndex, contentTop, contentBot, contentRoot);
else if (tabIndex == 1) totalPages = DrawGradients(elements, pageIndex, contentTop, contentBot, player, contentRoot);
else if (tabIndex == 2) totalPages = DrawPatterns(elements, pageIndex, contentTop, contentBot, player, contentRoot);
var footer = elements.Add(new CuiPanel { Image = { Color = "0 0 0 0.5" }, RectTransform = { AnchorMin = "0 0", AnchorMax = $"1 {relFooterH}" } }, contentRoot);
elements.Add(new CuiButton {
Button = { Color = "0.4 0.2 0.2 1", Command = "namecolor.clear" },
RectTransform = { AnchorMin = "0.75 0.1", AnchorMax = "0.98 0.9" },
Text = { Text = "RESET", Align = TextAnchor.MiddleCenter, FontSize = 10 }
}, footer);
float centerX = 0.5f;
float arrowW = 0.12f;
float textW = 0.2f;
float pageTextLeft = centerX - (textW / 2);
float pageTextRight = centerX + (textW / 2);
float leftArrowRight = pageTextLeft - 0.02f;
float leftArrowLeft = leftArrowRight - arrowW;
float rightArrowLeft = pageTextRight + 0.02f;
float rightArrowRight = rightArrowLeft + arrowW;
if (pageIndex > 0)
{
elements.Add(new CuiButton {
Button = { Color = "0.25 0.25 0.3 1", Command = $"namecolor.ui {tabIndex} {pageIndex - 1}" },
RectTransform = { AnchorMin = $"{leftArrowLeft} 0.1", AnchorMax = $"{leftArrowRight} 0.9" },
Text = { Text = "<", Align = TextAnchor.MiddleCenter }
}, footer);
}
elements.Add(new CuiLabel {
Text = { Text = $"PAGE {pageIndex + 1}/{totalPages}", Align = TextAnchor.MiddleCenter, FontSize = 10, Color = "0.6 0.6 0.6 1" },
RectTransform = { AnchorMin = $"{pageTextLeft} 0", AnchorMax = $"{pageTextRight} 1" }
}, footer);
if (pageIndex < totalPages - 1)
{
elements.Add(new CuiButton {
Button = { Color = "0.25 0.25 0.3 1", Command = $"namecolor.ui {tabIndex} {pageIndex + 1}" },
RectTransform = { AnchorMin = $"{rightArrowLeft} 0.1", AnchorMax = $"{rightArrowRight} 0.9" },
Text = { Text = ">", Align = TextAnchor.MiddleCenter }
}, footer);
}
CuiHelper.AddUi(player, elements);
}
private void DrawTabs(CuiElementContainer el, int active, float y, float h, BasePlayer p, string parent)
{
string[] names = { "COLORS", "GRADIENTS", "PATTERNS" };
bool hasGrad = permission.UserHasPermission(p.UserIDString, PermGradient);
bool hasPat = permission.UserHasPermission(p.UserIDString, PermPattern);
int count = 1 + (hasGrad?1:0) + (hasPat?1:0);
float w = 1f / count;
int visIdx = 0;
for (int i = 0; i < 3; i++)
{
if (i == 1 && !hasGrad) continue;
if (i == 2 && !hasPat) continue;
float left = visIdx * w;
float right = left + w;
bool isActive = (i == active);
el.Add(new CuiButton {
Button = { Color = isActive ? "0.25 0.25 0.35 1" : "0.15 0.15 0.2 1", Command = $"namecolor.ui {i} 0" },
RectTransform = { AnchorMin = $"{left} {y}", AnchorMax = $"{right} {y+h}" },
Text = { Text = names[i], Align = TextAnchor.MiddleCenter, FontSize = 11, Color = isActive ? "1 1 1 1" : "0.6 0.6 0.6 1" }
}, parent);
visIdx++;
}
}
private int DrawSolids(CuiElementContainer el, int page, float top, float bot, string parent)
{
var items = _config.SolidColors;
int count = items.Count;
int cols = _config.ColorsPerRow;
float margin = 0.02f;
float spacing = 0.015f;
float btnW = (1f - (2 * margin) - ((cols - 1) * spacing)) / cols;
float btnH = btnW * 0.47f;
float hPerItem = btnH + spacing;
float availableH = top - bot - margin;
int rowsPerPage = (int)(availableH / hPerItem);
int itemsPerPage = rowsPerPage * cols;
if (itemsPerPage <= 0) itemsPerPage = 1;
int totalPages = (count + itemsPerPage - 1) / itemsPerPage;
if (page >= totalPages) page = totalPages - 1;
if (page < 0) page = 0;
int startIndex = page * itemsPerPage;
int endIndex = Math.Min(startIndex + itemsPerPage, count);
float curY = top - margin;
float curX = margin;
for (int i = startIndex; i < endIndex; i++)
{
if (curX + btnW > 1f) { curX = margin; curY -= hPerItem; }
var c = items[i];
el.Add(new CuiButton {
Button = { Color = HexToCui(c.Hex), Command = $"namecolor.solid {c.Hex}" },
RectTransform = { AnchorMin = $"{curX} {curY - btnH}", AnchorMax = $"{curX + btnW} {curY}" },
Text = { Text = "" }
}, parent);
curX += btnW + spacing;
}
return totalPages;
}
private int DrawGradients(CuiElementContainer el, int page, float top, float bot, BasePlayer p, string parent)
{
var items = _config.Gradients;
int count = items.Count;
float itemH = 0.08f;
float spacing = 0.015f;
float hPerItem = itemH + spacing;
float availableH = top - bot - 0.01f;
int itemsPerPage = (int)(availableH / hPerItem);
if (itemsPerPage <= 0) itemsPerPage = 1;
int totalPages = (count + itemsPerPage - 1) / itemsPerPage;
if (page >= totalPages) page = totalPages - 1;
if (page < 0) page = 0;
int startIndex = page * itemsPerPage;
int endIndex = Math.Min(startIndex + itemsPerPage, count);
float curY = top - 0.01f;
for (int i = startIndex; i < endIndex; i++)
{
var g = items[i];
var panel = el.Add(new CuiPanel { Image = { Color = "0 0 0 0.3" }, RectTransform = { AnchorMin = $"0.05 {curY - itemH}", AnchorMax = $"0.95 {curY}" } }, parent);
float colorW = 1f / g.Colors.Length;
for(int c=0; c<g.Colors.Length; c++)
{
el.Add(new CuiPanel { Image = { Color = HexToCui(g.Colors[c]) }, RectTransform = { AnchorMin = $"{c*colorW} 0.4", AnchorMax = $"{c*colorW + colorW} 0.9" } }, panel);
}
el.Add(new CuiLabel { Text = { Text = g.Name, Align = TextAnchor.MiddleLeft, FontSize = 10 }, RectTransform = { AnchorMin = "0.05 0", AnchorMax = "0.7 0.4" } }, panel);
el.Add(new CuiButton {
Button = { Color = "0.3 0.6 0.3 0.8", Command = $"namecolor.grad {i}" },
RectTransform = { AnchorMin = "0.75 0.05", AnchorMax = "0.98 0.35" },
Text = { Text = "SET", Align = TextAnchor.MiddleCenter, FontSize = 9 }
}, panel);
curY -= hPerItem;
}
return totalPages;
}
private int DrawPatterns(CuiElementContainer el, int page, float top, float bot, BasePlayer p, string parent)
{
var items = _config.Patterns;
int count = items.Count;
float itemH = 0.08f;
float spacing = 0.015f;
float hPerItem = itemH + spacing;
float availableH = top - bot - 0.01f;
int itemsPerPage = (int)(availableH / hPerItem);
if (itemsPerPage <= 0) itemsPerPage = 1;
int totalPages = (count + itemsPerPage - 1) / itemsPerPage;
if (page >= totalPages) page = totalPages - 1;
if (page < 0) page = 0;
int startIndex = page * itemsPerPage;
int endIndex = Math.Min(startIndex + itemsPerPage, count);
float curY = top - 0.01f;
for (int i = startIndex; i < endIndex; i++)
{
var pat = items[i];
var panel = el.Add(new CuiPanel { Image = { Color = "0 0 0 0.3" }, RectTransform = { AnchorMin = $"0.05 {curY - itemH}", AnchorMax = $"0.95 {curY}" } }, parent);
int segments = 8;
float segW = 1f / segments;
for(int s=0; s<segments; s++)
{
string col = pat.Colors[s % pat.Colors.Length];
el.Add(new CuiPanel { Image = { Color = HexToCui(col) }, RectTransform = { AnchorMin = $"{s*segW} 0.4", AnchorMax = $"{s*segW + segW} 0.9" } }, panel);
}
el.Add(new CuiLabel { Text = { Text = pat.Name, Align = TextAnchor.MiddleLeft, FontSize = 10 }, RectTransform = { AnchorMin = "0.05 0", AnchorMax = "0.7 0.4" } }, panel);
el.Add(new CuiButton {
Button = { Color = "0.4 0.4 0.7 0.8", Command = $"namecolor.pat {i}" },
RectTransform = { AnchorMin = "0.75 0.05", AnchorMax = "0.98 0.35" },
Text = { Text = "SET", Align = TextAnchor.MiddleCenter, FontSize = 9 }
}, panel);
curY -= hPerItem;
}
return totalPages;
}
#endregion
#region Console Commands
[ConsoleCommand("namecolor.close")]
private void CC_Close(ConsoleSystem.Arg arg)
{
CuiHelper.DestroyUi(arg.Player(), LayerContent);
CuiHelper.DestroyUi(arg.Player(), LayerBase);
}
[ConsoleCommand("namecolor.ui")]
private void CC_UI(ConsoleSystem.Arg arg)
{
if (!arg.HasArgs(2)) return;
UpdateContentUI(arg.Player(), arg.GetInt(0), arg.GetInt(1));
}
[ConsoleCommand("namecolor.solid")]
private void CC_Solid(ConsoleSystem.Arg arg)
{
if (!arg.HasArgs(1)) return;
var hex = arg.GetString(0);
UpdateColor(arg.Player(), ColorType.Solid, hex, null);
CuiHelper.DestroyUi(arg.Player(), LayerContent);
CuiHelper.DestroyUi(arg.Player(), LayerBase);
if (_data.Players.TryGetValue(arg.Player().UserIDString, out var d))
SendReply(arg.Player(), $"Your color is now: {FormatName(arg.Player().displayName, d)}");
}
[ConsoleCommand("namecolor.grad")]
private void CC_Grad(ConsoleSystem.Arg arg)
{
if (!arg.HasArgs(1)) return;
var idx = arg.GetInt(0);
if (idx >= 0 && idx < _config.Gradients.Count)
{
var g = _config.Gradients[idx];
UpdateColor(arg.Player(), ColorType.Gradient, null, g.Colors);
CuiHelper.DestroyUi(arg.Player(), LayerContent);
CuiHelper.DestroyUi(arg.Player(), LayerBase);
if (_data.Players.TryGetValue(arg.Player().UserIDString, out var d))
SendReply(arg.Player(), $"Your color is now: {FormatName(arg.Player().displayName, d)}");
}
}
[ConsoleCommand("namecolor.pat")]
private void CC_Pat(ConsoleSystem.Arg arg)
{
if (!arg.HasArgs(1)) return;
var idx = arg.GetInt(0);
if (idx >= 0 && idx < _config.Patterns.Count)
{
var p = _config.Patterns[idx];
UpdateColor(arg.Player(), ColorType.Pattern, null, p.Colors);
CuiHelper.DestroyUi(arg.Player(), LayerContent);
CuiHelper.DestroyUi(arg.Player(), LayerBase);
if (_data.Players.TryGetValue(arg.Player().UserIDString, out var d))
SendReply(arg.Player(), $"Your color is now: {FormatName(arg.Player().displayName, d)}");
}
}
[ConsoleCommand("namecolor.clear")]
private void CC_Clear(ConsoleSystem.Arg arg)
{
if (_data.Players.Remove(arg.Player().UserIDString)) SaveData();
CuiHelper.DestroyUi(arg.Player(), LayerContent);
CuiHelper.DestroyUi(arg.Player(), LayerBase);
SendReply(arg.Player(), "Color reset.");
}
private void UpdateColor(BasePlayer p, ColorType type, string val, string[] colors)
{
if (!_data.Players.TryGetValue(p.UserIDString, out var d)) { d = new PlayerColorData(); _data.Players[p.UserIDString] = d; }
d.Type = (int)type;
d.Val = val;
d.Colors = colors;
d.Last = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
SaveData();
}
#endregion
}
}