Using static Regex functions that take in a pattern is bad because the pattern constantly needs to be re-parsed. With https://github.com/space-wizards/RobustToolbox/pull/5107, the engine has an analyzer to warn for this practice now.
This commit brings most of content up to snuff already, though some of the tricker code I left for somebody else.
{
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
+ private static readonly Regex RegexTh = new(@"th", RegexOptions.IgnoreCase);
+ private static readonly Regex RegexStartH = new(@"(?<!\w)h", RegexOptions.IgnoreCase);
+ private static readonly Regex RegexSpacePunctuation = new(@"(?<=\w\w)[!?;:](?!\w)", RegexOptions.IgnoreCase);
+
public override void Initialize()
{
base.Initialize();
msg = _replacement.ApplyReplacements(msg, "french");
- // replaces th with dz
- msg = Regex.Replace(msg, @"th", "'z", RegexOptions.IgnoreCase);
+ // replaces th with dz
+ msg = RegexTh.Replace(msg, "'z");
// removes the letter h from the start of words.
- msg = Regex.Replace(msg, @"(?<!\w)[h]", "'", RegexOptions.IgnoreCase);
+ msg = RegexStartH.Replace(msg, "'");
// spaces out ! ? : and ;.
- msg = Regex.Replace(msg, @"(?<=\w\w)!(?!\w)", " !", RegexOptions.IgnoreCase);
- msg = Regex.Replace(msg, @"(?<=\w\w)[?](?!\w)", " ?", RegexOptions.IgnoreCase);
- msg = Regex.Replace(msg, @"(?<=\w\w)[;](?!\w)", " ;", RegexOptions.IgnoreCase);
- msg = Regex.Replace(msg, @"(?<=\w\w)[:](?!\w)", " :", RegexOptions.IgnoreCase);
+ msg = RegexSpacePunctuation.Replace(msg, " $&");
return msg;
}
public sealed class FrontalLispSystem : EntitySystem
{
+ // @formatter:off
+ private static readonly Regex RegexUpperTh = new(@"[T]+[Ss]+|[S]+[Cc]+(?=[IiEeYy]+)|[C]+(?=[IiEeYy]+)|[P][Ss]+|([S]+[Tt]+|[T]+)(?=[Ii]+[Oo]+[Uu]*[Nn]*)|[C]+[Hh]+(?=[Ii]*[Ee]*)|[Z]+|[S]+|[X]+(?=[Ee]+)");
+ private static readonly Regex RegexLowerTh = new(@"[t]+[s]+|[s]+[c]+(?=[iey]+)|[c]+(?=[iey]+)|[p][s]+|([s]+[t]+|[t]+)(?=[i]+[o]+[u]*[n]*)|[c]+[h]+(?=[i]*[e]*)|[z]+|[s]+|[x]+(?=[e]+)");
+ private static readonly Regex RegexUpperEcks = new(@"[E]+[Xx]+[Cc]*|[X]+");
+ private static readonly Regex RegexLowerEcks = new(@"[e]+[x]+[c]*|[x]+");
+ // @formatter:on
+
public override void Initialize()
{
base.Initialize();
var message = args.Message;
// handles ts, sc(i|e|y), c(i|e|y), ps, st(io(u|n)), ch(i|e), z, s
- message = Regex.Replace(message, @"[T]+[Ss]+|[S]+[Cc]+(?=[IiEeYy]+)|[C]+(?=[IiEeYy]+)|[P][Ss]+|([S]+[Tt]+|[T]+)(?=[Ii]+[Oo]+[Uu]*[Nn]*)|[C]+[Hh]+(?=[Ii]*[Ee]*)|[Z]+|[S]+|[X]+(?=[Ee]+)", "TH");
- message = Regex.Replace(message, @"[t]+[s]+|[s]+[c]+(?=[iey]+)|[c]+(?=[iey]+)|[p][s]+|([s]+[t]+|[t]+)(?=[i]+[o]+[u]*[n]*)|[c]+[h]+(?=[i]*[e]*)|[z]+|[s]+|[x]+(?=[e]+)", "th");
+ message = RegexUpperTh.Replace(message, "TH");
+ message = RegexLowerTh.Replace(message, "th");
// handles ex(c), x
- message = Regex.Replace(message, @"[E]+[Xx]+[Cc]*|[X]+", "EKTH");
- message = Regex.Replace(message, @"[e]+[x]+[c]*|[x]+", "ekth");
+ message = RegexUpperEcks.Replace(message, "EKTH");
+ message = RegexLowerEcks.Replace(message, "ekth");
args.Message = message;
}
public sealed class LizardAccentSystem : EntitySystem
{
+ private static readonly Regex RegexLowerS = new("s+");
+ private static readonly Regex RegexUpperS = new("S+");
+ private static readonly Regex RegexInternalX = new(@"(\w)x");
+ private static readonly Regex RegexLowerEndX = new(@"\bx([\-|r|R]|\b)");
+ private static readonly Regex RegexUpperEndX = new(@"\bX([\-|r|R]|\b)");
+
public override void Initialize()
{
base.Initialize();
var message = args.Message;
// hissss
- message = Regex.Replace(message, "s+", "sss");
+ message = RegexLowerS.Replace(message, "sss");
// hiSSS
- message = Regex.Replace(message, "S+", "SSS");
+ message = RegexUpperS.Replace(message, "SSS");
// ekssit
- message = Regex.Replace(message, @"(\w)x", "$1kss");
+ message = RegexInternalX.Replace(message, "$1kss");
// ecks
- message = Regex.Replace(message, @"\bx([\-|r|R]|\b)", "ecks$1");
+ message = RegexLowerEndX.Replace(message, "ecks$1");
// eckS
- message = Regex.Replace(message, @"\bX([\-|r|R]|\b)", "ECKS$1");
+ message = RegexUpperEndX.Replace(message, "ECKS$1");
args.Message = message;
}
-using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Content.Server.Speech.Components;
public sealed class MobsterAccentSystem : EntitySystem
{
+ private static readonly Regex RegexIng = new(@"(?<=\w\w)(in)g(?!\w)", RegexOptions.IgnoreCase);
+ private static readonly Regex RegexLowerOr = new(@"(?<=\w)o[Rr](?=\w)");
+ private static readonly Regex RegexUpperOr = new(@"(?<=\w)O[Rr](?=\w)");
+ private static readonly Regex RegexLowerAr = new(@"(?<=\w)a[Rr](?=\w)");
+ private static readonly Regex RegexUpperAr = new(@"(?<=\w)A[Rr](?=\w)");
+ private static readonly Regex RegexFirstWord = new(@"^(\S+)");
+ private static readonly Regex RegexLastWord = new(@"(\S+)$");
+
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
- private static readonly Dictionary<string, string> DirectReplacements = new()
- {
- { "let me", "lemme" },
- { "should", "oughta" },
- { "the", "da" },
- { "them", "dem" },
- { "attack", "whack" },
- { "kill", "whack" },
- { "murder", "whack" },
- { "dead", "sleepin' with da fishies"},
- { "hey", "ey'o" },
- { "hi", "ey'o"},
- { "hello", "ey'o"},
- { "rules", "roolz" },
- { "you", "yous" },
- { "have to", "gotta" },
- { "going to", "boutta" },
- { "about to", "boutta" },
- { "here", "'ere" }
- };
-
public override void Initialize()
{
base.Initialize();
// thinking -> thinkin'
// king -> king
//Uses captures groups to make sure the captialization of IN is kept
- msg = Regex.Replace(msg, @"(?<=\w\w)(in)g(?!\w)", "$1'", RegexOptions.IgnoreCase);
+ msg = RegexIng.Replace(msg, "$1'");
// or -> uh and ar -> ah in the middle of words (fuhget, tahget)
- msg = Regex.Replace(msg, @"(?<=\w)o[Rr](?=\w)", "uh");
- msg = Regex.Replace(msg, @"(?<=\w)O[Rr](?=\w)", "UH");
- msg = Regex.Replace(msg, @"(?<=\w)a[Rr](?=\w)", "ah");
- msg = Regex.Replace(msg, @"(?<=\w)A[Rr](?=\w)", "AH");
+ msg = RegexLowerOr.Replace(msg, "uh");
+ msg = RegexUpperOr.Replace(msg, "UH");
+ msg = RegexLowerAr.Replace(msg, "ah");
+ msg = RegexUpperAr.Replace(msg, "AH");
// Prefix
if (_random.Prob(0.15f))
{
//Checks if the first word of the sentence is all caps
//So the prefix can be allcapped and to not resanitize the captial
- var firstWordAllCaps = !Regex.Match(msg, @"^(\S+)").Value.Any(char.IsLower);
+ var firstWordAllCaps = !RegexFirstWord.Match(msg).Value.Any(char.IsLower);
var pick = _random.Next(1, 2);
// Reverse sanitize capital
{
//Checks if the last word of the sentence is all caps
//So the suffix can be allcapped
- var lastWordAllCaps = !Regex.Match(msg, @"(\S+)$").Value.Any(char.IsLower);
+ var lastWordAllCaps = !RegexLastWord.Match(msg).Value.Any(char.IsLower);
var suffix = "";
if (component.IsBoss)
{
else
{
var pick = _random.Next(1, 3);
- suffix = Loc.GetString($"accent-mobster-suffix-minion-{pick}");
+ suffix = Loc.GetString($"accent-mobster-suffix-minion-{pick}");
}
if (lastWordAllCaps)
suffix = suffix.ToUpper();
public sealed class MothAccentSystem : EntitySystem
{
+ private static readonly Regex RegexLowerBuzz = new Regex("z{1,3}");
+ private static readonly Regex RegexUpperBuzz = new Regex("Z{1,3}");
+
public override void Initialize()
{
base.Initialize();
var message = args.Message;
// buzzz
- message = Regex.Replace(message, "z{1,3}", "zzz");
+ message = RegexLowerBuzz.Replace(message, "zzz");
// buZZZ
- message = Regex.Replace(message, "Z{1,3}", "ZZZ");
-
+ message = RegexUpperBuzz.Replace(message, "ZZZ");
+
args.Message = message;
}
}
public sealed partial class ParrotAccentSystem : EntitySystem
{
+ private static readonly Regex WordCleanupRegex = new Regex("[^A-Za-z0-9 -]");
+
[Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
if (_random.Prob(entity.Comp.LongestWordRepeatChance))
{
// Don't count non-alphanumeric characters as parts of words
- var cleaned = Regex.Replace(message, "[^A-Za-z0-9 -]", string.Empty);
+ var cleaned = WordCleanupRegex.Replace(message, string.Empty);
// Split on whitespace and favor words towards the end of the message
var words = cleaned.Split(null).Reverse();
// Find longest word
public sealed class PirateAccentSystem : EntitySystem
{
+ private static readonly Regex FirstWordAllCapsRegex = new(@"^(\S+)");
+
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
return msg;
//Checks if the first word of the sentence is all caps
//So the prefix can be allcapped and to not resanitize the captial
- var firstWordAllCaps = !Regex.Match(msg, @"^(\S+)").Value.Any(char.IsLower);
+ var firstWordAllCaps = !FirstWordAllCapsRegex.Match(msg).Value.Any(char.IsLower);
var pick = _random.Pick(component.PirateWords);
var pirateWord = Loc.GetString(pick);
{
public sealed class ScrambledAccentSystem : EntitySystem
{
+ private static readonly Regex RegexLoneI = new(@"(?<=\ )i(?=[\ \.\?]|$)");
+
[Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
msg = msg[0].ToString().ToUpper() + msg.Remove(0, 1);
// Capitalize lone i's
- msg = Regex.Replace(msg, @"(?<=\ )i(?=[\ \.\?]|$)", "I");
+ msg = RegexLoneI.Replace(msg, "I");
return msg;
}
public sealed class SouthernAccentSystem : EntitySystem
{
+ private static readonly Regex RegexIng = new(@"ing\b");
+ private static readonly Regex RegexAnd = new(@"\band\b");
+ private static readonly Regex RegexDve = new("d've");
+
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
-
+
public override void Initialize()
{
base.Initialize();
message = _replacement.ApplyReplacements(message, "southern");
//They shoulda started runnin' an' hidin' from me!
- message = Regex.Replace(message, @"ing\b", "in'");
- message = Regex.Replace(message, @"\band\b", "an'");
- message = Regex.Replace(message, "d've", "da");
+ message = RegexIng.Replace(message, "in'");
+ message = RegexAnd.Replace(message, "an'");
+ message = RegexDve.Replace(message, "da");
args.Message = message;
}
};
[Serializable, NetSerializable]
public sealed partial class HumanoidCharacterProfile : ICharacterProfile
{
+ private static readonly Regex RestrictedNameRegex = new("[^A-Z,a-z,0-9, -]");
+ private static readonly Regex ICNameCaseRegex = new(@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)");
+
public const int MaxNameLength = 32;
public const int MaxDescLength = 512;
if (configManager.GetCVar(CCVars.RestrictedNames))
{
- name = Regex.Replace(name, @"[^A-Z,a-z,0-9, -]", string.Empty);
+ name = RestrictedNameRegex.Replace(name, string.Empty);
}
if (configManager.GetCVar(CCVars.ICNameCase))
{
// This regex replaces the first character of the first and last words of the name with their uppercase version
- name = Regex.Replace(name,
- @"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
- m => m.Groups["word"].Value.ToUpper());
+ name = ICNameCaseRegex.Replace(name, m => m.Groups["word"].Value.ToUpper());
}
if (string.IsNullOrEmpty(name))