Skip to content

Commit

Permalink
Rewrote the chat patch.
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielWillett committed Nov 8, 2024
1 parent f3f64fd commit 0c2e1e6
Show file tree
Hide file tree
Showing 25 changed files with 959 additions and 400 deletions.
3 changes: 2 additions & 1 deletion UncreatedWarfare/Commands/Kit/KitRenameCommand.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using Uncreated.Warfare.Database.Abstractions;
using Uncreated.Warfare.Interaction;
using Uncreated.Warfare.Interaction.Commands;
using Uncreated.Warfare.Kits;
using Uncreated.Warfare.Logging;
Expand Down Expand Up @@ -76,7 +77,7 @@ public async UniTask ExecuteAsync(CancellationToken token)
throw Context.SendHelp();
}

if (Data.GetChatFilterViolation(name) is { } filterViolation)
if (ChatFilterHelper.GetChatFilterViolation(name) is { } filterViolation)
{
throw Context.Reply(_translations.KitRenameFilterVoilation, filterViolation);
}
Expand Down
62 changes: 0 additions & 62 deletions UncreatedWarfare/Data.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public static class Paths

public const string SuppressCategory = "Microsoft.Performance";
public const string SuppressID = "IDE0051";
public static readonly Regex ChatFilter = new Regex(@"(?:[nńǹňñṅņṇṋṉn̈ɲƞᵰᶇɳȵɴnŋnjvṼṽṿʋᶌᶌⱱⱴᴠʌv\|\\\/]\W{0,}[il1ÍíìĭîǐïḯĩįīỉȉȋịḭɨᵻᶖiıɪɩifiIij\|\!]\W{0,}[gqb96ǴǵğĝǧġģḡǥɠᶃɢȝgŋɢɢɋƣʠqȹḂḃḅḇƀɓƃᵬᶀʙbȸ](?!h|(?:an)|(?:[e|a|o]t)|(?:un)|(?:rab)|(?:rain)|(?:low)|(?:ue)|(?:uy))(?!n\shadi)\W{0,}[gqb96ǴǵğĝǧġģḡǥɠᶃɢȝgŋɢɢɋƣʠqȹḂḃḅḇƀɓƃᵬᶀʙbȸ]{0,}\W{0,}[gqb96ǴǵğĝǧġģḡǥɠᶃɢȝgŋɢɢɋƣʠqȹḂḃḅḇƀɓƃᵬᶀʙbȸ]{0,}\W{0,}[ae]{0,1}\W{0,}[r]{0,}(?:ia){0,})|(?:c\W{0,}h\W{0,}i{1,}\W{0,}n{1,}\W{0,}k{1,})|(?:[fḟƒᵮᶂꜰfffffifflfifl]\W{0,}[aáàâǎăãảȧạäåḁāąᶏⱥȁấầẫẩậắằẵẳặǻǡǟȃɑᴀɐɒaæᴁᴭᵆǽǣᴂ]\W{0,}[gqb96ǴǵğĝǧġģḡǥɠᶃɢȝgŋɢɢɋƣʠqȹḂḃḅḇƀɓƃᵬᶀʙbȸ]{1,}\W{0,}o{0,}\W{0,}t{0,1}(?!ain))", RegexOptions.IgnoreCase);
public static readonly Regex PluginKeyMatch = new Regex(@"\<plugin_\d\/\>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static CultureInfo LocalLocale = Languages.CultureEnglishUS; // todo set from config
public static Dictionary<ulong, UCPlayerData> PlaytimeComponents;
Expand Down Expand Up @@ -117,67 +116,6 @@ public static PooledTransportConnectionList GetPooledTransportConnectionList(IEn
rtn.AddRange(selector);
return rtn;
}
private static readonly char[] TrimChars = [ '.', '?', '\\', '/', '-', '=', '_', ',' ];
public static string? GetChatFilterViolation(string input)
{
Match match = ChatFilter.Match(input);
if (!match.Success || match.Length <= 0)
return null;

string matchValue = match.Value.TrimEnd().TrimEnd(TrimChars);
int len1 = matchValue.Length;
matchValue = matchValue.TrimStart().TrimStart(TrimChars);

int matchIndex = match.Index + (len1 - matchValue.Length);

static bool IsPunctuation(char c)
{
for (int i = 0; i < TrimChars.Length; ++i)
if (TrimChars[i] == c)
return true;

return false;
}

// whole word
if ((matchIndex == 0 || char.IsWhiteSpace(input[matchIndex - 1]) || char.IsPunctuation(input[matchIndex - 1])) &&
(matchIndex + matchValue.Length >= input.Length || char.IsWhiteSpace(input[matchIndex + matchValue.Length]) || IsPunctuation(input[matchIndex + matchValue.Length])))
{
// vibe matches the filter
if (matchValue.Equals("vibe", StringComparison.InvariantCultureIgnoreCase))
{
return null;
}
}
// .. can i be .. or .. can i go ..
if (matchIndex - 2 >= 0 && input.Substring(matchIndex - 2, 2) is { } sub &&
(sub.Equals("ca", StringComparison.InvariantCultureIgnoreCase) || sub.Equals("ma", StringComparison.InvariantCultureIgnoreCase)))
{
if ((matchIndex + matchValue.Length >= input.Length || char.IsWhiteSpace(input[matchIndex + matchValue.Length]) || IsPunctuation(input[matchIndex + matchValue.Length]))
&& matchValue.Equals("n i be", StringComparison.InvariantCultureIgnoreCase))
return null;

if ((matchIndex + matchValue.Length < input.Length && input[matchIndex + matchValue.Length].ToString().Equals("o", StringComparison.InvariantCultureIgnoreCase))
&& matchValue.Equals("n i g", StringComparison.InvariantCultureIgnoreCase))
return null;
}
else if (matchIndex - 2 > 0 && input.Substring(matchIndex - 1, 1).Equals("o", StringComparison.InvariantCultureIgnoreCase)
&& !(matchIndex + matchValue.Length >= input.Length || char.IsWhiteSpace(input[matchIndex + matchValue.Length + 1]) || IsPunctuation(input[matchIndex + matchValue.Length])))
{
// .. of a g___
if (matchValue.Equals("f a g", StringComparison.InvariantCultureIgnoreCase))
return null;
}
// .. an igla ..
else if (matchValue.Equals("n ig", StringComparison.InvariantCultureIgnoreCase) && matchIndex > 0 &&
input[matchIndex - 1].ToString().Equals("a", StringComparison.InvariantCultureIgnoreCase) &&
matchIndex < input.Length - 2 && input.Substring(matchIndex + matchValue.Length, 2).Equals("la", StringComparison.InvariantCultureIgnoreCase))
{
return null;
}

return matchValue;
}

internal static readonly List<KeyValuePair<Type, string?>> TranslatableEnumTypes = new List<KeyValuePair<Type, string?>>()
{
Expand Down
41 changes: 1 addition & 40 deletions UncreatedWarfare/EventFunctions.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Uncreated.Framework.UI;
using Uncreated.Warfare.Commands;
using Uncreated.Warfare.Components;
using Uncreated.Warfare.Configuration;
using Uncreated.Warfare.Database;
using Uncreated.Warfare.Database.Abstractions;
using Uncreated.Warfare.Deaths;
using Uncreated.Warfare.Events;
using Uncreated.Warfare.Events.Components;
using Uncreated.Warfare.Events.Models;
using Uncreated.Warfare.Events.Models.Barricades;
using Uncreated.Warfare.Events.Models.Items;
using Uncreated.Warfare.Events.Models.Players;
using Uncreated.Warfare.Events.Models.Structures;
using Uncreated.Warfare.Events.Models.Vehicles;
using Uncreated.Warfare.Interaction;
using Uncreated.Warfare.Kits;
using Uncreated.Warfare.Layouts.UI;
using Uncreated.Warfare.Components;
using Uncreated.Warfare.Logging;
using Uncreated.Warfare.Models.Assets;
using Uncreated.Warfare.Models.Kits;
using Uncreated.Warfare.Models.Localization;
using Uncreated.Warfare.Models.Stats.Records;
using Uncreated.Warfare.Moderation;
using Uncreated.Warfare.Moderation.Records;
using Uncreated.Warfare.Players;
using Uncreated.Warfare.Players.Management.Legacy;
using Uncreated.Warfare.Players.UI;
using Uncreated.Warfare.Quests;
using Uncreated.Warfare.Squads;
using Uncreated.Warfare.Stats;
using Uncreated.Warfare.Teams;
using Uncreated.Warfare.Traits;
using Uncreated.Warfare.Traits.Buffs;
using Uncreated.Warfare.Util;
using Uncreated.Warfare.Vehicles;
using Uncreated.Warfare.Zones;

#pragma warning disable IDE0060 // Remove unused parameter
namespace Uncreated.Warfare;
Expand Down
81 changes: 81 additions & 0 deletions UncreatedWarfare/Events/Models/Players/PlayerChatRequested.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using Uncreated.Warfare.Players;

namespace Uncreated.Warfare.Events.Models.Players;

/// <summary>
/// Invoked when a player tries to send a chat message.
/// </summary>
[EventModel(SynchronizationContext = EventSynchronizationContext.PerPlayer)]
public class PlayerChatRequested : CancellablePlayerEvent
{
private EChatMode _chatMode;

/// <summary>
/// The text that will be sent to everyone else.
/// </summary>
public required string Text { get; set; }

/// <summary>
/// If the caller has permission to bypass checks for chat.
/// </summary>
public required bool HasAdminChatPermissions { get; init; }

/// <summary>
/// The original text the player sent.
/// </summary>
public required string OriginalText { get; init; }

/// <summary>
/// The player's names to be formatted into the message for each player.
/// </summary>
public required PlayerNames PlayerName { get; set; }

/// <summary>
/// The text that will be sent in front of the message.
/// </summary>
public required string Prefix { get; set; }

/// <summary>
/// The color of the message.
/// </summary>
public required Color MessageColor { get; set; }

/// <summary>
/// If the message came from an event hook.
/// </summary>
public required bool IsUnityMessage { get; init; }

/// <summary>
/// If rich text should be allowed.
/// </summary>
public required bool AllowRichText { get; set; }

/// <summary>
/// Custom icon to use instead of the player's profile picture.
/// </summary>
/// <remarks><see langword="null"/> = the sender's profile picture.</remarks>
public string? IconUrlOverride { get; set; }

/// <summary>
/// The broadcast mode.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException"/>
public required EChatMode ChatMode
{
get => _chatMode;
set
{
if (value is not EChatMode.GLOBAL and not EChatMode.LOCAL and not EChatMode.GROUP)
throw new ArgumentOutOfRangeException(nameof(value));

_chatMode = value;
}
}

/// <summary>
/// Getter for a list of all players the message should be sent to.
/// </summary>
public required Func<PlayerChatRequested, IEnumerable<WarfarePlayer>> TargetPlayers { get; set; }
}
50 changes: 50 additions & 0 deletions UncreatedWarfare/Events/Models/Players/PlayerChatSent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Uncreated.Warfare.Players;

namespace Uncreated.Warfare.Events.Models.Players;

/// <summary>
/// Invoked after a player sends a chat message.
/// </summary>
public class PlayerChatSent : PlayerEvent
{
/// <summary>
/// The text that will be sent to everyone else.
/// </summary>
public required string Text { get; init; }

/// <summary>
/// The original text the player sent.
/// </summary>
public required string OriginalText { get; init; }

/// <summary>
/// The player's names to be formatted into the message for each player.
/// </summary>
public required PlayerNames PlayerName { get; init; }

/// <summary>
/// The text that will be sent in front of the message.
/// </summary>
public required string Prefix { get; init; }

/// <summary>
/// The color of the message.
/// </summary>
public required Color MessageColor { get; init; }

/// <summary>
/// If rich text should be allowed.
/// </summary>
public required bool AllowRichText { get; init; }

/// <summary>
/// Custom icon to use instead of the player's profile picture.
/// </summary>
/// <remarks><see langword="null"/> = the sender's profile picture.</remarks>
public string? IconUrlOverride { get; init; }

/// <summary>
/// The broadcast mode.
/// </summary>
public required EChatMode ChatMode { get; init; }
}
Loading

0 comments on commit 0c2e1e6

Please sign in to comment.