C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using ConVar;
using UnityEngine;
using CompanionServer;
using Pool = Facepunch.Pool;
using Random = System.Random;
namespace Oxide.Plugins
{
[Info("Coloured Chat", "collect_vood", "2.2.87")]
[Description("Allows players to change their name & message colour in chat")]
class ColouredChat : CovalencePlugin
{
[PluginReference]
private Plugin BetterChat, BetterChatMute, ZoneManager;
#region Fields
private readonly StringBuilder _sharedStringBuilder = new StringBuilder();
private const string ColourRegex = "^#(?:[0-9a-fA-f]{3}){1,2}$";
private const string ChatFormat = "{0}: {1}";
#endregion
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>()
{
{ "NoPermission", "You don't have permission to use this command." },
{ "NoPermissionSetOthers", "You don't have permission to set other players {0} colours." },
{ "NoPermissionGradient", "You don't have permission to use {0} gradients." },
{ "NoPermissionRandom", "You don't have permission to use random {0} colours." },
{ "NoPermissionRainbow", "You don't have permission to use the rainbow colours." },
{ "IncorrectGradientUsage", "Incorrect usage! To use gradients please use /{0} gradient hexCode1 hexCode2...</color>" },
{ "IncorrectGradientUsageArgs", "Incorrect usage! A gradient requires at least two different valid colours!"},
{ "GradientChanged", "{0} gradient changed to {1}!"},
{ "GradientChangedFor", "{0}'s gradient {1} colour changed to {2}!"},
{ "IncorrectUsage", "Incorrect usage! /{0} <colour>\nFor detailed help do /{1}" },
{ "IncorrectSetUsage", "Incorrect set usage! /{0} set <playerIdOrName> <colourOrColourArgument>\nFor a list of colours do /colours" },
{ "PlayerNotFound", "Player {0} was not found." },
{ "InvalidCharacters", "The character '{0}' is not allowed in colours.Please remove it." },
{ "ColourRemoved", "{0} colour removed!" },
{ "ColourRemovedFor", "{0}'s {1} colour was removed!" },
{ "ColourChanged", "{0} colour changed to <color={1}>{1}</color>!" },
{ "ColourChangedFor", "{0}'s {1} colour changed to <color={2}>{2}</color>!" },
{ "ColoursInfo", "You can only use hexcodes, eg '<color=#ffff94>#ffff94</color>'\nTo remove your colour, use 'clear', 'reset' or 'remove'\n\nAvailable Commands: {0}\n\n{1}"},
{ "InvalidColour", "That colour is not valid.Do /colours for more information on valid colours." },
{ "RndColour", "{0} colour was randomized to <color={1}>{1}</color>" },
{ "RndColourFor", "{0} colour of {1} randomized to <color={2}>{2}</color>."},
{ "RainbowColour", "{0} colour was set to rainbow." },
{ "RainbowColourFor", "{0} colour of {1} set to rainbow."},
{ "IncorrectGroupUsage", "Incorrect group usage! /{0} group <groupName> <colourOrColourArgument>\nFor a list of colours do /colours" },
}, this);
lang.RegisterMessages(new Dictionary<string, string>()
{
{ "NoPermission", "У вас нет прав для использования этой команды." },
{ "NoPermissionSetOthers", "У вас нет прав для изменения цвета другим игрокам({0})." },
{ "NoPermissionGradient", "У вас нет разрешения на использование градиентов {0}.." },
{ "NoPermissionRandom", "У вас нет разрешения на использование случайных цветов {0}.." },
{ "NoPermissionRainbow", "У вас нет разрешения на использование цветов радуги.." },
{ "IncorrectGradientUsage", "Неправильное использование! Чтобы использовать градиенты, используйте градиент /{0} hexCode1 hexCode2....</color>" },
{ "IncorrectGradientUsageArgs", "Неправильное использование! Для градиента требуется как минимум два разных допустимых цвета.!"},
{ "GradientChanged", "{0} градиент изменен на {1}!"},
{ "GradientChangedFor", "Цвет градиента {1} объекта {0} изменен на {2}."},
{ "IncorrectUsage", "Неправильное использование! /{0} <color>\\nДля получения подробной информации выполните /{1}" },
{ "IncorrectSetUsage", "Неправильное использование набора! /{0} set <playerIdOrName> <colourOrColourArgument>\\nДля списка цветов выполните /colours" },
{ "PlayerNotFound", "Игрок {0} не найден." },
{ "InvalidCharacters", "Символ «{0}» не допускается в цветах.Пожалуйста, удалите его." },
{ "ColourRemoved", "Цвет {0} удален!" },
{ "ColourRemovedFor", "Цвет {1} у пользователя {0} был удален!" },
{ "ColourChanged", "Цвет {0} изменен на <color={1}>{1}</color>!" },
{ "ColourChangedFor", "Цвет {1} объекта {0} изменен на <color={2}>{2}</color>!" },
{ "ColoursInfo", "Вы можете использовать только шестнадцатеричные коды, например, '<color=#ffff94>#ffff94</color>'\\nЧтобы удалить цвет, используйте «очистить», «сбросить» или «удалить».\\n\\nДоступные команды: {0}\\n \\n{1}"},
{ "InvalidColour", "Этот цвет недействителен.Чтобы получить дополнительную информацию о допустимых цветах, выполните команду /colors." },
{ "RndColour", "Цвет {0} был рандомизирован на <color={1}>{1}</color>" },
{ "RndColourFor", "Цвет {0} из {1} рандомизирован на <color={2}>{2}</color>."},
{ "RainbowColour", "Цвет {0} был установлен на радугу." },
{ "RainbowColourFor", "{0} цвет {1} установлен на радугу."},
{ "IncorrectGroupUsage", "Неправильное использование группы! /{0} group <groupName> <colourOrColourArgument>\\nДля списка цветов выполните /colours" },
}, this);
}
#endregion
#region Config
private Configuration _configuration;
private class Configuration
{
//General
[JsonProperty(PropertyName = "Player Inactivity Data Removal (days)")]
public int InactivityRemovalTime = 7;
[JsonProperty(PropertyName = "Block messages of muted players (requires BetterChatMute)")]
public bool BlockChatMute = true;
[JsonProperty(PropertyName = "Rainbow Colours")]
public string[] RainbowColours = { "#ff0000", "#ffa500", "#ffff94", "#008000", "#0000ff", "#4b0082", "#ee82ee" };
[JsonProperty(PropertyName = "Blocked Characters")]
public string[] BlockedValues = { "{", "}", "size" };
//Name
[JsonProperty(PropertyName = "Name colour commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] NameColourCommands = new string[] { "colour", "color" };
[JsonProperty(PropertyName = "Name colour commands (Help)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] NameColoursCommands = new string[] { "colours", "colors" };
[JsonProperty(PropertyName = "Name show colour permission")]
public string NamePermShow = "colouredchat.name.show";
[JsonProperty(PropertyName = "Name use permission")]
public string NamePermUse = "colouredchat.name.use";
[JsonProperty(PropertyName = "Name use gradient permission")]
public string NamePermGradient = "colouredchat.name.gradient";
[JsonProperty(PropertyName = "Name default rainbow name permission")]
public string NamePermRainbow = "colouredchat.name.rainbow";
[JsonProperty(PropertyName = "Name bypass restrictions permission")]
public string NamePermBypass = "colouredchat.name.bypass";
[JsonProperty(PropertyName = "Name set others colour permission")]
public string NamePermSetOthers = "colouredchat.name.setothers";
[JsonProperty(PropertyName = "Name get random colour permission")]
public string NamePermRandomColour = "colouredchat.name.random";
[JsonProperty(PropertyName = "Name use blacklist")]
public bool NameUseBlacklist = true;
[JsonProperty(PropertyName = "Name blocked colour hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> NameBlockColoursHex = new List<string>
{
{ "#000000" }
};
[JsonProperty(PropertyName = "Name blocked colours range hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ColourRange> NameBlacklistedRangeColoursHex = new List<ColourRange>
{
{ new ColourRange("#000000", "#000000") }
};
[JsonProperty(PropertyName = "Name use whitelist")]
public bool NameUseWhitelist = false;
[JsonProperty(PropertyName = "Name whitelisted colours hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> NameWhitelistedColoursHex = new List<string>
{
{ "#000000" }
};
[JsonProperty(PropertyName = "Name whitelisted colour range hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ColourRange> NameWhitelistedRangeColoursHex = new List<ColourRange>
{
{ new ColourRange("#000000", "#FFFFFF") }
};
//Message
[JsonProperty(PropertyName = "Message colour commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] MessageColourCommands = new string[] { "mcolour", "mcolor" };
[JsonProperty(PropertyName = "Message colour commands (Help)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] MessageColoursCommands = new string[] { "mcolours", "mcolors" };
[JsonProperty(PropertyName = "Message show colour permission")]
public string MessagePermShow = "colouredchat.message.show";
[JsonProperty(PropertyName = "Message use permission")]
public string MessagePermUse = "colouredchat.message.use";
[JsonProperty(PropertyName = "Message use gradient permission")]
public string MessagePermGradient = "colouredchat.message.gradient";
[JsonProperty(PropertyName = "Message default rainbow name permission")]
public string MessagePermRainbow = "colouredchat.message.rainbow";
[JsonProperty(PropertyName = "Message bypass restrictions permission")]
public string MessagePermBypass = "colouredchat.message.bypass";
[JsonProperty(PropertyName = "Message set others colour permission")]
public string MessagePermSetOthers = "colouredchat.message.setothers";
[JsonProperty(PropertyName = "Message get random colour permission")]
public string MessagePermRandomColour = "colouredchat.message.random";
[JsonProperty(PropertyName = "Message use blacklist")]
public bool MessageUseBlacklist = true;
[JsonProperty(PropertyName = "Message blocked colours hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> MessageBlockColoursHex = new List<string>
{
{ "#000000" }
};
[JsonProperty(PropertyName = "Message blocked colour range hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ColourRange> MessageBlacklistedRangeColoursHex = new List<ColourRange>
{
{ new ColourRange("#000000", "#000000") }
};
[JsonProperty(PropertyName = "Message use whitelist")]
public bool MessageUseWhitelist = false;
[JsonProperty(PropertyName = "Message whitelisted colours hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> MessageWhitelistedColoursHex = new List<string>
{
{ "#000000" }
};
[JsonProperty(PropertyName = "Message whitelisted colour range hex", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ColourRange> MessageWhitelistedRangeColoursHex = new List<ColourRange>
{
{ new ColourRange("#000000", "#FFFFFF") }
};
}
protected override void LoadDefaultConfig()
{
PrintWarning("Creating a new configuration file");
_configuration = new Configuration();
}
protected override void LoadConfig()
{
base.LoadConfig();
_configuration = Config.ReadObject<Configuration>();
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(_configuration);
#region Colour Range Class
public class ColourRange
{
[JsonProperty(PropertyName = "From")]
public string _from;
[JsonProperty(PropertyName = "To")]
public string _to;
public ColourRange(string from, string to)
{
_from = from;
_to = to;
}
}
#endregion
#endregion
#region Data
private Dictionary<string, CachePlayerData> cachedData = new Dictionary<string, CachePlayerData>();
private StoredData storedData;
private Dictionary<string, PlayerData> allColourData => storedData.AllColourData;
private class StoredData
{
public Dictionary<string, PlayerData> AllColourData { get; private set; } = new Dictionary<string, PlayerData>();
}
private class PlayerData
{
[JsonProperty("Name Colour")]
public string NameColour = string.Empty;
[JsonProperty("Name Gradient Args")]
public string[] NameGradientArgs = null;
[JsonProperty("Message Colour")]
public string MessageColour = string.Empty;
[JsonProperty("Message Gradient Args")]
public string[] MessageGradientArgs = null;
[JsonProperty("Last active")]
public long LastActive = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
public PlayerData()
{
}
public PlayerData(string nameColour = "", string[] nameGradientArgs = null, string messageColour = "", string[] messageGradientArgs = null)
{
NameColour = nameColour;
NameGradientArgs = nameGradientArgs;
MessageColour = messageColour;
MessageGradientArgs = messageGradientArgs;
}
public PlayerData(bool isGroup)
{
LastActive = 0;
}
}
private class CachePlayerData
{
public string NameColourGradient;
public string PrimaryGroup;
public CachePlayerData(string nameColourGradient = "", string primaryGroup = "")
{
NameColourGradient = nameColourGradient;
PrimaryGroup = primaryGroup;
}
}
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, storedData);
private void OnServerSave()
{
ClearUpData();
SaveData();
}
private void Unload() => SaveData();
private void ChangeNameColour(string key, string colour, string[] colourArgs)
{
var playerData = new PlayerData(colour, colourArgs);
if (!allColourData.ContainsKey(key)) allColourData.Add(key, playerData);
allColourData[key].NameColour = colour;
allColourData[key].NameGradientArgs = colourArgs;
}
private void ChangeMessageColour(string key, string colour, string[] colourArgs)
{
var playerData = new PlayerData(string.Empty, null, colour, colourArgs);
if (!allColourData.ContainsKey(key)) allColourData.Add(key, playerData);
allColourData[key].MessageColour = colour;
allColourData[key].MessageGradientArgs = colourArgs;
}
#endregion
#region Hooks
private void Init()
{
if (_configuration.MessageUseBlacklist && _configuration.MessageUseWhitelist || _configuration.NameUseBlacklist && _configuration.NameUseWhitelist) PrintWarning("You are using both black/- and whitelist! This might cause issues.");
permission.RegisterPermission(_configuration.NamePermShow, this);
permission.RegisterPermission(_configuration.MessagePermShow, this);
permission.RegisterPermission(_configuration.NamePermRainbow, this);
permission.RegisterPermission(_configuration.MessagePermRainbow, this);
permission.RegisterPermission(_configuration.NamePermGradient, this);
permission.RegisterPermission(_configuration.MessagePermGradient, this);
permission.RegisterPermission(_configuration.NamePermUse, this);
permission.RegisterPermission(_configuration.MessagePermUse, this);
permission.RegisterPermission(_configuration.NamePermBypass, this);
permission.RegisterPermission(_configuration.MessagePermBypass, this);
permission.RegisterPermission(_configuration.NamePermSetOthers, this);
permission.RegisterPermission(_configuration.MessagePermSetOthers, this);
permission.RegisterPermission(_configuration.NamePermRandomColour, this);
permission.RegisterPermission(_configuration.MessagePermRandomColour, this);
AddCovalenceCommand(_configuration.NameColourCommands, nameof(cmdNameColour));
AddCovalenceCommand(_configuration.NameColoursCommands, nameof(cmdNameColours));
AddCovalenceCommand(_configuration.MessageColourCommands, nameof(cmdMessageColour));
AddCovalenceCommand(_configuration.MessageColoursCommands, nameof(cmdMessageColours));
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
ClearUpData();
}
private void OnUserConnected(IPlayer player)
{
if (!allColourData.ContainsKey(player.Id)) return;
allColourData[player.Id].LastActive = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
private void OnUserDisconnected(IPlayer player)
{
if (!allColourData.ContainsKey(player.Id)) return;
allColourData[player.Id].LastActive = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
private void OnUserNameUpdated(string id, string oldName, string newName) => ClearCache(id);
private void OnUserGroupAdded(string id, string groupName) => ClearCache(id);
private void OnUserGroupRemoved(string id, string groupName) => ClearCache(id);
private void OnGroupDeleted(string name) => ClearCache();
private void OnGroupPermissionGranted(string name, string perm) => ClearCache();
private void OnGroupPermissionRevoked(string name, string perm) => ClearCache();
private object OnPlayerChat(BasePlayer player, string message, Chat.ChatChannel channel)
{
if (BetterChatIns())
return null;
if (_configuration.BlockChatMute && BetterChatMuteIns())
if (BetterChatMute.Call<bool>("API_IsMuted", player.IPlayer))
return null;
if (player == null)
return null;
if (ZoneManagerIns() && ZoneManager.Call<bool>("PlayerHasFlag", player, "nochat"))
return false;
if (Chat.serverlog)
{
var objArray = new object[] { ConsoleColor.DarkYellow, null, null, null };
objArray[1] = string.Concat(new object[] { "[", channel, "] ", player.displayName.EscapeRichText(), ": " });
objArray[2] = ConsoleColor.DarkGreen;
objArray[3] = message;
ServerConsole.PrintColoured(objArray);
}
var colouredChatMessage = FromMessage(player.IPlayer, channel, message);
var colouredChatMessageDict = colouredChatMessage.GetDictionary();
#region API
foreach (var plugin in plugins.GetAll())
{
var obj = plugin.CallHook("OnColouredChat", colouredChatMessageDict);
if (obj is Dictionary<string, object>)
{
try
{
colouredChatMessageDict = obj as Dictionary<string, object>;
}
catch (Exception e)
{
PrintError($"Failed to load modified OnColouredChat hook data from plugin '{plugin.Title} ({plugin.Version})':{Environment.NewLine}{e}");
continue;
}
}
else if (obj != null) return obj;
}
colouredChatMessage = ColouredChatMessage.FromDictionary(colouredChatMessageDict);
#endregion
SendMessage(colouredChatMessage);
return true;
}
private Dictionary<string, object> OnBetterChat(Dictionary<string, object> dict)
{
if (dict != null)
{
var player = dict["Player"] as IPlayer;
var colouredChatMessage = FromMessage(player, (Chat.ChatChannel)dict["ChatChannel"],
dict["Message"].ToString());
#region API
var colouredChatMessageDict = colouredChatMessage.GetDictionary();
foreach (Plugin plugin in plugins.GetAll())
{
object obj = plugin.CallHook("OnColouredChat", colouredChatMessageDict);
if (obj is Dictionary<string, object>)
{
try
{
colouredChatMessageDict = obj as Dictionary<string, object>;
}
catch (Exception e)
{
PrintError($"Failed to load modified OnColouredChat hook data from plugin '{plugin.Title} ({plugin.Version})':{Environment.NewLine}{e}");
continue;
}
}
else if (obj != null)
{
if (obj is bool)
{
dict["CancelOption"] = 2;
}
}
}
colouredChatMessage = ColouredChatMessage.FromDictionary(colouredChatMessageDict);
#endregion
if (!string.IsNullOrEmpty(colouredChatMessage.Name)) dict["Username"] = colouredChatMessage.Name;
if (!string.IsNullOrEmpty(colouredChatMessage.Colour)) { ((Dictionary<string, object>)dict["UsernameSettings"])["Color"] = colouredChatMessage.Colour; }
dict["Message"] = colouredChatMessage.Message;
}
return dict;
}
#endregion
#region Commands
void cmdNameColour(IPlayer player, string cmd, string[] args) => ProcessColourCommand(player, cmd, args);
void cmdNameColours(IPlayer player, string cmd, string[] args) => ProcessColoursCommand(player, cmd, args);
void cmdMessageColour(IPlayer player, string cmd, string[] args) => ProcessColourCommand(player, cmd, args, true);
void cmdMessageColours(IPlayer player, string cmd, string[] args) => ProcessColoursCommand(player, cmd, args, true);
#endregion
#region Helpers
private bool BetterChatIns() => (BetterChat != null && BetterChat.IsLoaded);
private bool BetterChatMuteIns() => (BetterChatMute != null && BetterChatMute.IsLoaded);
private bool ZoneManagerIns() => (ZoneManager != null && ZoneManager.IsLoaded);
private bool IsValidColour(string input) => Regex.Match(input, ColourRegex).Success;
private string GetMessage(string key, IPlayer player, params string[] args) => $"<color=#cdc2b2>{string.Format(lang.GetMessage(key, this, player.Id), args)}</color>";
//Name
private bool HasNameShowPerm(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.NamePermShow));
private bool HasNamePerm(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.NamePermUse));
private bool HasNameRainbow(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.NamePermRainbow));
private bool CanNameGradient(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.NamePermGradient));
private bool CanNameBypass(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.NamePermBypass));
private bool CanNameSetOthers(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.NamePermSetOthers));
private bool CanNameRandomColour(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.NamePermRandomColour));
//Message
private bool HasMessageShowPerm(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.MessagePermShow));
private bool HasMessagePerm(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.MessagePermUse));
private bool HasMessageRainbow(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.MessagePermRainbow));
private bool CanMessageGradient(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.MessagePermGradient));
private bool CanMessageBypass(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.MessagePermBypass));
private bool CanMessageSetOthers(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.MessagePermSetOthers));
private bool CanMessageRandomColour(IPlayer player) => (player.IsAdmin || permission.UserHasPermission(player.Id, _configuration.MessagePermRandomColour));
private bool IsValidName(string input, IPlayer iPlayer = null)
{
if (iPlayer != null && CanNameBypass(iPlayer)) return true;
if (_configuration.NameUseBlacklist)
{
bool inRange = false;
foreach (var colourRange in _configuration.NameBlacklistedRangeColoursHex)
{
inRange = IsInHexRange(input, colourRange._from, colourRange._to);
if (inRange) break;
}
return !_configuration.NameBlockColoursHex.Any(x => (input == x)) && !inRange;
}
else if (_configuration.NameUseWhitelist)
{
bool inRange = false;
foreach (var colourRange in _configuration.NameWhitelistedRangeColoursHex)
{
inRange = IsInHexRange(input, colourRange._from, colourRange._to);
if (!inRange) break;
}
return _configuration.NameWhitelistedColoursHex.Any(x => (input == x)) || inRange;
}
return true;
}
private bool IsValidMessage(string input, IPlayer iPlayer = null)
{
if (iPlayer != null && CanMessageBypass(iPlayer)) return true;
if (_configuration.MessageUseBlacklist)
{
bool inRange = false;
foreach (var colourRange in _configuration.MessageBlacklistedRangeColoursHex)
{
inRange = IsInHexRange(input, colourRange._from, colourRange._to);
if (inRange)
break;
}
return !_configuration.MessageBlockColoursHex.Any(x => (input == x)) && !inRange;
}
else if (_configuration.MessageUseWhitelist)
{
bool inRange = false;
foreach (var colourRange in _configuration.MessageWhitelistedRangeColoursHex)
{
inRange = IsInHexRange(input, colourRange._from, colourRange._to);
if (!inRange)
break;
}
return _configuration.MessageWhitelistedColoursHex.Any(x => (input == x)) || inRange;
}
return true;
}
private void SendMessage(ColouredChatMessage colouredChatMessage)
{
var player = colouredChatMessage.Player.Object as BasePlayer;
if (player == null)
return; // cannot send if player does not exist
var formattedLogMessage = _sharedStringBuilder;
formattedLogMessage.Clear();
switch (colouredChatMessage.ChatChannel)
{
case Chat.ChatChannel.Global:
case Chat.ChatChannel.Server:
{
ConsoleNetwork.BroadcastToAllClients("chat.add2", (int) colouredChatMessage.ChatChannel,
player.userID, colouredChatMessage.Message, colouredChatMessage.Name,
colouredChatMessage.Colour);
formattedLogMessage.Append("[CHAT] ");
break;
}
case Chat.ChatChannel.Team:
{
if (player.Team == null)
return;
// Broadcast to rust+ app users
player.Team.BroadcastTeamChat(player.userID, player.displayName, colouredChatMessage.Message, colouredChatMessage.Colour);
ConsoleNetwork.SendClientCommand(player.Team.GetOnlineMemberConnections(), "chat.add2",
(int) colouredChatMessage.ChatChannel, player.userID, colouredChatMessage.Message,
colouredChatMessage.Name, colouredChatMessage.Colour);
formattedLogMessage.Append("[TEAM CHAT] ");
break;
}
case Chat.ChatChannel.Cards:
{
if (!player.isMounted)
return;
var cardTable = player.GetMountedVehicle() as CardTable;
if (cardTable == null || !cardTable.GameController.PlayerIsInGame(player))
return;
var cardTableConnections = Pool.GetList<Network.Connection>();
cardTable.GameController.GetConnectionsInGame(cardTableConnections);
if (cardTableConnections.Count > 0)
{
ConsoleNetwork.SendClientCommand(cardTableConnections, "chat.add2",
(int) colouredChatMessage.ChatChannel, player.userID, colouredChatMessage.Message,
colouredChatMessage.Name, colouredChatMessage.Colour);
}
Pool.FreeList(ref cardTableConnections);
formattedLogMessage.Append("[CARDS CHAT] ");
break;
}
case Chat.ChatChannel.Local:
{
var num = Chat.localChatRange * Chat.localChatRange;
var senderPosition = player.transform.position;
var closeByConnections = Pool.GetList<Network.Connection>();
foreach (var basePlayer in BasePlayer.activePlayerList)
{
var sqrMagnitude = (basePlayer.transform.position - senderPosition).sqrMagnitude;
if (sqrMagnitude > num)
continue;
closeByConnections.Add(basePlayer.Connection);
}
ConsoleNetwork.SendClientCommand(closeByConnections, "chat.add2",
(int) colouredChatMessage.ChatChannel, player.userID, colouredChatMessage.Message,
colouredChatMessage.Name, colouredChatMessage.Colour);
Pool.FreeList(ref closeByConnections);
formattedLogMessage.Append("[CHAT] ");
break;
}
}
// Console logging
formattedLogMessage.Append(player.displayName.EscapeRichText()).Append('[').Append(player.UserIDString).Append("] : ").Append(colouredChatMessage.Message);
DebugEx.Log(formattedLogMessage);
// Rcon logging
var chatEntry = new Chat.ChatEntry
{
Channel = colouredChatMessage.ChatChannel,
Message = colouredChatMessage.Message,
UserId = player.UserIDString,
Username = player.displayName,
Color = colouredChatMessage.Colour,
Time = Facepunch.Math.Epoch.Current
};
Facepunch.RCon.Broadcast(Facepunch.RCon.LogType.Chat, chatEntry);
}
private void ProcessColourCommand(IPlayer player, string cmd, string[] args, bool isMessage = false)
{
if (args.Length < 1)
{
Player.Message(player.Object as BasePlayer, GetMessage("IncorrectUsage", player,
isMessage ? _configuration.MessageColourCommands[0] : _configuration.NameColourCommands[0],
isMessage ? _configuration.MessageColoursCommands[0] : _configuration.NameColoursCommands[0]),76561198297741077);
return;
}
var colLower = string.Empty;
if (args[0] == "set")
{
if ((!isMessage && !CanNameSetOthers(player)) || (isMessage && !CanMessageSetOthers(player)))
{
Player.Message(player.Object as BasePlayer, GetMessage("NoPermissionSetOthers", player, isMessage ? "message" : "name"),76561198297741077);
return;
}
if (args.Length < 3)
{
Player.Message(player.Object as BasePlayer, GetMessage("IncorrectSetUsage", player,
isMessage ? _configuration.MessageColourCommands[0] : _configuration.NameColourCommands[0]),76561198297741077);
return;
}
var target = covalence.Players.FindPlayer(args[1]);
if (target == null)
{
Player.Message(player.Object as BasePlayer, GetMessage("PlayerNotFound", player, args[1]),76561198297741077);
return;
}
colLower = args[2].ToLower();
ProcessColour(player, target, colLower, args.Skip(2).ToArray(), isMessage);
}
else if (args[0] == "group")
{
if (!player.IsAdmin)
{
Player.Message(player.Object as BasePlayer, GetMessage("NoPermission", player),76561198297741077);
return;
}
if (args.Length < 3)
{
Player.Message(player.Object as BasePlayer, GetMessage("IncorrectGroupUsage", player,
isMessage ? _configuration.MessageColourCommands[0] : _configuration.NameColourCommands[0]),76561198297741077);
return;
}
if (!permission.GroupExists(args[1])) permission.CreateGroup(args[1], string.Empty, 0);
colLower = args[2].ToLower();
ProcessColour(player, player, colLower, args.Skip(3).ToArray(), isMessage, args[1]);
}
else
{
if ((!isMessage && !HasNamePerm(player)) || (isMessage && !HasMessagePerm(player)))
{
Player.Message(player.Object as BasePlayer, GetMessage("NoPermission", player),76561198297741077);
return;
}
if (args.Length < 1)
{
Player.Message(player.Object as BasePlayer, GetMessage("IncorrectUsage", player,
isMessage ? _configuration.MessageColourCommands[0] : _configuration.NameColourCommands[0]),76561198297741077);
return;
}
colLower = args[0].ToLower();
ProcessColour(player, player, colLower, args.Skip(1).ToArray(), isMessage);
}
}
private void ProcessColoursCommand(IPlayer player, string cmd, string[] args, bool isMessage = false)
{
if ((!isMessage && !HasNamePerm(player)) || (isMessage && !HasMessagePerm(player)))
{
Player.Message(player.Object as BasePlayer, GetMessage("NoPermission", player),76561198297741077);
return;
}
var availableCommandsBuilder = _sharedStringBuilder;
availableCommandsBuilder.Clear();
if (isMessage)
{
var commandName = _configuration.MessageColourCommands[0];
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" <color=#ff6666>#ff6666</color>");
if (CanMessageRandomColour(player))
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" random");
}
if (CanMessageGradient(player))
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" gradient <color=#ff6666>#ff6666</color> <color=#ff6666>#ff6666</color>").AppendLine();
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" gradient <color=#ff6666>#ff6666</color> <color=#ffff94>#ffff94</color> <color=#90ee90>#90ee90</color>");
}
if (CanMessageSetOthers(player))
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" set <color=#a8a8a8>playerIdOrName</color> <color=#ff6666>#ff6666</color>");
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" set <color=#a8a8a8>playerIdOrName</color> gradient <color=#ff6666>#ff6666</color> <color=#ffff94>#ffff94</color>");
}
if (player.IsAdmin)
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" group <color=#a8a8a8>groupName</color> <color=#ff6666>#ff6666</color>");
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" group <color=#a8a8a8>groupName</color> gradient <color=#ff6666>#ff6666</color> <color=#ffff94>#ffff94</color>");
}
}
else
{
var commandName = _configuration.NameColourCommands[0];
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" <color=#ff6666>#ff6666</color>");
if (CanNameRandomColour(player))
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" random");
}
if (CanNameGradient(player))
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" gradient <color=#ff6666>#ff6666</color> <color=#ff6666>#ff6666</color>").AppendLine();
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" gradient <color=#ff6666>#ff6666</color> <color=#ffff94>#ffff94</color> <color=#90ee90>#90ee90</color>");
}
if (CanNameSetOthers(player))
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" set <color=#a8a8a8>playerIdOrName</color> <color=#ff6666>#ff6666</color>");
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" set <color=#a8a8a8>playerIdOrName</color> gradient <color=#ff6666>#ff6666</color> <color=#ffff94>#ffff94</color>");
}
if (player.IsAdmin)
{
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" group <color=#a8a8a8>groupName</color> <color=#ff6666>#ff6666</color>");
availableCommandsBuilder.AppendLine().Append('/').Append(commandName).Append(" group <color=#a8a8a8>groupName</color> gradient <color=#ff6666>#ff6666</color> <color=#ffff94>#ffff94</color>");
}
}
var availableCommands = availableCommandsBuilder.ToString();
var additionalInfoBuilder = _sharedStringBuilder;
additionalInfoBuilder.Clear();
if (isMessage && _configuration.MessageUseWhitelist)
{
additionalInfoBuilder.AppendLine("Whitelisted Colours:");
foreach (var colour in _configuration.MessageWhitelistedColoursHex)
{
additionalInfoBuilder.Append("- <color=").Append(colour).Append(">").Append(colour).AppendLine("</color>");
}
foreach (var colourRange in _configuration.MessageWhitelistedRangeColoursHex)
{
additionalInfoBuilder.Append("- From <color=").Append(colourRange._from).Append(">").Append(colourRange._from).Append("</color> to <color=").Append(colourRange._to).Append(">").Append(colourRange._to).AppendLine("</color>");
}
}
else if (isMessage && _configuration.MessageUseBlacklist)
{
additionalInfoBuilder.AppendLine("Blacklisted Colours:");
foreach (var colour in _configuration.MessageBlockColoursHex)
{
additionalInfoBuilder.Append("- <color=").Append(colour).Append(">").Append(colour).Append("</color>");
}
foreach (var colourRange in _configuration.MessageBlacklistedRangeColoursHex)
{
additionalInfoBuilder.Append("- From <color=").Append(colourRange._from).Append(">").Append(colourRange._from).Append("</color> to <color=").Append(colourRange._to).Append(">").Append(colourRange._to).AppendLine("</color>");
}
}
else if (!isMessage && _configuration.NameUseWhitelist)
{
additionalInfoBuilder.AppendLine("Whitelisted Colours:");
foreach (var colour in _configuration.NameWhitelistedColoursHex)
{
additionalInfoBuilder.Append("- <color=").Append(colour).Append(">").Append(colour).AppendLine("</color>");
}
foreach (var colourRange in _configuration.NameWhitelistedRangeColoursHex)
{
additionalInfoBuilder.Append("- From <color=").Append(colourRange._from).Append(">").Append(colourRange._from).Append("</color> to <color=").Append(colourRange._to).Append(">").Append(colourRange._to).AppendLine("</color>");
}
}
else if (!isMessage && _configuration.NameUseBlacklist)
{
additionalInfoBuilder.AppendLine("Blacklisted Colours:");
foreach (var colour in _configuration.NameBlockColoursHex)
{
additionalInfoBuilder.Append("- <color=").Append(colour).Append(">").Append(colour).AppendLine("</color>");
}
foreach (var colourRange in _configuration.NameBlacklistedRangeColoursHex)
{
additionalInfoBuilder.Append("- From <color=").Append(colourRange._from).Append(">").Append(colourRange._from).Append("</color> to <color=").Append(colourRange._to).Append(">").Append(colourRange._to).AppendLine("</color>");
}
}
Player.Message(player.Object as BasePlayer, GetMessage("ColoursInfo", player, availableCommands, additionalInfoBuilder.ToString()),76561198297741077);
}
private string ProcessColourMessage(string message, string colour) => $"<color={colour}>" + message + "</color>";
private void ProcessColour(IPlayer player, IPlayer target, string colLower, string[] colours, bool isMessage = false, string groupName = "")
{
var isGroup = !string.IsNullOrEmpty(groupName);
var isCalledOnto = player != target && !isGroup;
var key = isGroup ? groupName : target.Id;
if (!isGroup && !allColourData.ContainsKey(target.Id)) allColourData.Add(target.Id, new PlayerData());
else if (isGroup && !allColourData.ContainsKey(groupName)) allColourData.Add(groupName, new PlayerData(true));
if (colLower == "gradient")
{
if ((!isMessage && !CanNameGradient(player)) || (isMessage && !CanMessageGradient(player)))
{
Player.Message(player.Object as BasePlayer, GetMessage("NoPermissionGradient", player, isMessage ? "message" : "name"),76561198297741077);
return;
}
colours = colours.Where(col =>
isMessage
? IsValidMessage(col, player)
: IsValidName(col, player) && IsValidColour(col) &&
IsInvalidCharacter(col) == null).ToArray();
if (colours.Length < 2)
{
Player.Message(player.Object as BasePlayer, GetMessage("IncorrectGradientUsageArgs", player,
isMessage ? _configuration.MessageColourCommands[0] : _configuration.NameColourCommands[0]),76561198297741077);
return;
}
string gradientName = ProcessGradient(isMessage ? "Example Message" : target.Name, colours, isMessage, player);
if (gradientName.Equals(string.Empty))
{
Player.Message(player.Object as BasePlayer, GetMessage("IncorrectGradientUsage", player,
isMessage ? _configuration.MessageColourCommands[0] : _configuration.NameColourCommands[0]),76561198297741077);
return;
}
if (isMessage)
{
allColourData[key].MessageColour = string.Empty;
allColourData[key].MessageGradientArgs = colours;
}
// ... [Code preview truncated due to length. Full source in attached file] ...