-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPlayerStore.cs
137 lines (117 loc) · 3.65 KB
/
PlayerStore.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using MowChat.Data;
namespace MowChat
{
public class PlayerStore
{
/// <summary>
/// A section of a message, optionally mentioning a character name.
/// </summary>
public class MessageSection
{
public string Text { get; private set; }
public IHasCharacterData CharacterMention { get; private set; }
public MessageSection(string text, IHasCharacterData character = null)
{
Text = text;
CharacterMention = character;
}
}
/// <summary>
/// The instance of the API singleton.
/// </summary>
private static PlayerStore _instance;
/// <summary>
/// The instance of the API singleton.
/// </summary>
public static PlayerStore Instance
{
get { return _instance ?? (_instance = new PlayerStore()); }
}
/// <summary>
/// Dictionary of all seen users.
/// </summary>
private Dictionary<string, IHasCharacterData> Characters { get; set; }
/// <summary>
/// A regex pattern to match any known player name.
/// </summary>
private string Pattern { get; set; }
/// <summary>
/// Constructor.
/// </summary>
private PlayerStore()
{
Characters = new Dictionary<string, IHasCharacterData>();
}
/// <summary>
/// Add a character to the player store.
/// </summary>
/// <param name="c">The character to add.</param>
public void StorePlayer(IHasCharacterData c)
{
if (c.Name == null)
{
var cm = c as ChatMessage;
if (cm != null && cm.Character != null)
StorePlayer(cm.Character);
return;
}
var lowerName = c.Name.ToLowerInvariant();
if (Characters.ContainsKey(lowerName)) return;
Characters.Add(lowerName, c);
Pattern = null;
}
/// <summary>
/// Check if a piece of text mentions the currently selected character.
/// </summary>
/// <param name="text">The text to check.</param>
/// <returns>True if the text contains the name of the current character.</returns>
public static bool TextContainsMe(string text)
{
return Regex.IsMatch(text, API.Instance.CurrentUser.SelectedCharacter.Name, RegexOptions.IgnoreCase);
}
/// <summary>
/// Find all references to a player in a piece of text, and return the text split up in
/// sections of non-mentions and mentions.
/// </summary>
/// <param name="text">The text to check.</param>
/// <returns>A list of text sections.</returns>
public IEnumerable<MessageSection> FindPlayerReferences(string text)
{
var pattern = CompilePattern();
var matches = Regex.Matches(text, pattern, RegexOptions.IgnoreCase);
var result = new List<MessageSection>();
// Extract each match from the text
foreach (Match match in matches)
{
// Find part in text before mention
var index = text.IndexOf(match.Value, StringComparison.Ordinal);
if (index > 0)
{
result.Add(new MessageSection(text.Substring(0, index)));
}
// Add the character mention to the result and continue after that
var lowerMatch = match.Value.ToLowerInvariant();
var character = Characters.ContainsKey(lowerMatch) ? Characters[lowerMatch] : null;
result.Add(new MessageSection(text.Substring(index, match.Value.Length), character));
text = text.Substring(index + match.Value.Length);
}
// Always add the remainder
if (text.Length > 0)
result.Add(new MessageSection(text));
return result;
}
/// <summary>
/// Create a regex pattern to match any registered player name.
/// </summary>
/// <returns>A regex pattern.</returns>
private string CompilePattern()
{
if (string.IsNullOrEmpty(Pattern))
Pattern = "(" + string.Join("|", Characters.Keys) + ")";
return Pattern;
}
}
}