-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathAPI.cs
228 lines (188 loc) · 9.9 KB
/
API.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
using System.Diagnostics;
using MelonLoader;
namespace Kafe.ChatBox;
public static class API {
private const string OSCModName = "OSC";
/// <summary>
/// The ChatBoxMessage class encapsulates details about a chat message received by the local player.
/// This can be triggered by various sources such as Internal, OSC, or external Mods.
/// </summary>
public class ChatBoxMessage {
/// <summary>
/// The source of the chat message, which can be Internal, OSC, or external Mod.
/// </summary>
public readonly MessageSource Source;
/// <summary>
/// The unique identifier (GUID) of the player who sent the chat message.
/// </summary>
public readonly string SenderGuid;
/// <summary>
/// The raw text content of the chat message that was received.
/// </summary>
public readonly string Message;
/// <summary>
/// A flag indicating whether a notification should be triggered for this chat message.
/// </summary>
public readonly bool TriggerNotification;
/// <summary>
/// A flag indicating whether this chat message should be displayed in the chat box.
/// </summary>
public readonly bool DisplayOnChatBox;
/// <summary>
/// A flag indicating whether this chat message should be displayed in the history window.
/// </summary>
public readonly bool DisplayOnHistory;
/// <summary>
/// The name of the mod in case it was sent via Mod.
/// </summary>
public readonly string ModName;
internal ChatBoxMessage(MessageSource source, string senderGuid, string message, bool triggerNotification, bool displayOnChatBox, bool displayOnHistory, string modName) {
Source = source;
SenderGuid = senderGuid;
Message = message;
TriggerNotification = triggerNotification;
DisplayOnChatBox = displayOnChatBox;
DisplayOnHistory = displayOnHistory;
ModName = modName;
}
}
/// <summary>
/// The ChatBoxTyping class encapsulates details about a typing event received by the local player.
/// This can be triggered by various sources such as Internal, OSC, or external Mods.
/// </summary>
public class ChatBoxTyping {
/// <summary>
/// The source of the typing event, which can be Internal, OSC, or external Mod.
/// </summary>
public readonly MessageSource Source;
/// <summary>
/// The unique identifier (GUID) of the player who triggered the typing event.
/// </summary>
public readonly string SenderGuid;
/// <summary>
/// A flag indicating whether the player is currently typing. True if typing, false otherwise.
/// </summary>
public readonly bool IsTyping;
/// <summary>
/// A flag indicating whether a notification (e.g., a sound) should be triggered for this typing event.
/// </summary>
public readonly bool TriggerNotification;
internal ChatBoxTyping(MessageSource source, string senderGuid, bool isTyping, bool triggerNotification) {
Source = source;
SenderGuid = senderGuid;
IsTyping = isTyping;
TriggerNotification = triggerNotification;
}
}
/// <summary>
/// This action is triggered whenever the local player sends a message to the Network.
/// </summary>
public static Action<ChatBoxMessage> OnMessageSent;
/// <summary>
/// This action is triggered whenever the local player receives a ChatBox message from the Network.
/// </summary>
public static Action<ChatBoxMessage> OnMessageReceived;
/// <summary>
/// This action is triggered whenever the local player sends a is typing event to the Network.
/// </summary>
public static Action<ChatBoxTyping> OnIsTypingSent;
/// <summary>
/// This action is triggered whenever the local player receives a is typing event from the Network.
/// </summary>
public static Action<ChatBoxTyping> OnIsTypingReceived;
/// <summary>
/// Where the message was sent from.
/// </summary>
public enum MessageSource : byte {
Internal,
OSC,
Mod,
}
/// <summary>
/// Sends a message through the ChatBox.
/// </summary>
/// <param name="message">The message to be sent through the ChatBox.</param>
/// <param name="sendSoundNotification">Whether to send a sounds notification or not.</param>
/// <param name="displayInChatBox">Whether to display the message on the ChatBox or not.</param>
/// <param name="displayInHistory">Whether to display the message on the History Window or not.</param>
public static void SendMessage(string message, bool sendSoundNotification, bool displayInChatBox, bool displayInHistory) {
var modName = GetModName();
var source = modName == OSCModName ? MessageSource.OSC : MessageSource.Mod;
ModNetwork.SendMessage(source, modName, message, sendSoundNotification, displayInChatBox, displayInHistory);
}
/// <summary>
/// Sets the typing status of the local player.
/// </summary>
/// <param name="isTyping">A boolean value indicating whether the local player is typing. Set to true if the player is typing, and false if the player is not typing.</param>
/// <param name="sendSoundNotification">Whether to send a sounds notification or not.</param>
public static void SetIsTyping(bool isTyping, bool sendSoundNotification) {
ChatBox.SetIsTyping(GetModName() == OSCModName ? MessageSource.OSC : MessageSource.Mod, isTyping, sendSoundNotification);
}
/// <summary>
/// Opens the in-game keyboard, with an optional initial message.
/// </summary>
/// <param name="initialMessage">The initial message to be displayed on the keyboard when it is opened. This can be an empty string.</param>
public static void OpenKeyboard(string initialMessage = "") {
ChatBox.OpenKeyboard(initialMessage, false);
}
internal static readonly HashSet<Func<ChatBoxMessage, InterceptorResult>> ReceivingInterceptors = new();
internal static readonly HashSet<Func<ChatBoxMessage, InterceptorResult>> SendingInterceptors = new();
/// <summary>
/// Allows adding an interceptor to RECEIVED messages to override the display of the messages.
/// </summary>
/// <param name="interceptor">The handler that receives a message and is waiting for a result. You need to create one.
/// For the result you can use `InterceptorResult.Ignore` if you don't want to override the message.</param>
public static void AddReceivingInterceptor(Func<ChatBoxMessage, InterceptorResult> interceptor) => ReceivingInterceptors.Add(interceptor);
/// <summary>
/// Allows removing a previously added interceptor to RECEIVED messages to override the display of the messages.
/// </summary>
/// <param name="interceptor">A reference for the interceptor previously added.</param>
public static void RemoveReceivingInterceptor(Func<ChatBoxMessage, InterceptorResult> interceptor) => ReceivingInterceptors.Remove(interceptor);
/// <summary>
/// Allows adding an interceptor to SENT messages to override the display of the messages.
/// </summary>
/// <param name="interceptor">The handler that receives a message and is waiting for a result. You need to create one.
/// For the result you can use `InterceptorResult.Ignore` if you don't want to override the message.</param>
public static void AddSendingInterceptor(Func<ChatBoxMessage, InterceptorResult> interceptor) => SendingInterceptors.Add(interceptor);
/// <summary>
/// Allows removing a previously added interceptor to SENT messages to override the display of the messages.
/// </summary>
/// <param name="interceptor">A reference for the interceptor previously added.</param>
public static void RemoveSendingInterceptor(Func<ChatBoxMessage, InterceptorResult> interceptor) => SendingInterceptors.Remove(interceptor);
/// <summary>
/// Class representing the result of an Interception. Use `InterceptorResult.Ignore` as a result if you don't want to affect the message.
/// </summary>
public class InterceptorResult {
public readonly string ModName;
public readonly bool PreventDisplayOnChatBox;
public readonly bool PreventDisplayOnHistory;
/// <summary>
/// Instance of an InterceptorResult that does not affect the message. You should use this when you want the interceptor to be ignored.
/// </summary>
public static readonly InterceptorResult Ignore = new(false, false);
/// <summary>
/// Create an interceptor to prevent certain messages from being displayed either on the ChatBox or History Window.
/// </summary>
/// <param name="preventDisplayOnChatBox"></param> Whether it should prevent displaying on ChatBox or not.
/// <param name="preventDisplayOnHistory"></param> Whether it should prevent displaying on History Window or not.
public InterceptorResult(bool preventDisplayOnChatBox, bool preventDisplayOnHistory) {
PreventDisplayOnChatBox = preventDisplayOnChatBox;
PreventDisplayOnHistory = preventDisplayOnHistory;
ModName = GetModName();
}
}
private static string GetModName() {
try {
var callingFrame = new StackTrace().GetFrame(2);
var callingAssembly = callingFrame.GetMethod().Module.Assembly;
var callingMelonAttr = callingAssembly.CustomAttributes.FirstOrDefault(
attr => attr.AttributeType == typeof(MelonInfoAttribute));
return (string) callingMelonAttr!.ConstructorArguments[1].Value;
}
catch (Exception ex) {
MelonLogger.Error("[GetModName] Attempted to get a mod's name...");
MelonLogger.Error(ex);
}
return "N/A";
}
}