//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.GameLogic.PlayerActions.Chat;
using MUnique.OpenMU.GameLogic.Views;
///
/// Action to send chat messages.
///
public class ChatMessageAction
{
private readonly IDictionary _messagePrefixes;
private readonly IDictionary _chatProcessMessages;
///
/// Initializes a new instance of the class.
///
public ChatMessageAction()
{
this._messagePrefixes = new SortedDictionary(new ReverseComparer())
{
{ "~", ChatMessageType.Party },
{ "@", ChatMessageType.Guild },
{ "@@", ChatMessageType.Alliance },
{ "$", ChatMessageType.Gens },
{ "!", ChatMessageType.GlobalNotification },
{ "/", ChatMessageType.Command },
};
this._chatProcessMessages = new Dictionary
{
{ ChatMessageType.Command, new ChatMessageCommandProcessor() },
{ ChatMessageType.Whisper, new ChatMessageWhisperProcessor() },
{ ChatMessageType.Party, new ChatMessagePartyProcessor() },
{ ChatMessageType.Alliance, new ChatMessageAllianceProcessor() },
{ ChatMessageType.Guild, new ChatMessageGuildProcessor() },
{ ChatMessageType.GlobalNotification, new ChatMessageGlobalNotificationProcessor() },
{ ChatMessageType.Normal, new ChatMessageNormalProcessor() },
};
}
///
/// Sends a chat message from the player to other players.
///
/// The sender.
/// Name of the , except for , then its the receiver name.
/// The message which should be sent.
/// If set to true the message is whispered to the player with the ; Otherwise, it's not a whisper.
public async ValueTask ChatMessageAsync(Player sender, string playerName, string message, bool whisper)
{
using var loggerScope = sender.Logger.BeginScope(this.GetType());
ChatMessageType messageType = this.GetMessageType(message, whisper);
if (sender.SelectedCharacter is null)
{
// Is possible to receive null?
return;
}
if (messageType != ChatMessageType.Whisper && playerName != sender.SelectedCharacter?.Name)
{
sender.Logger.LogWarning("Maybe Hacker, Charname in chat packet != charname\t [{0}] <> [{1}]", sender.SelectedCharacter?.Name, playerName);
}
if (!this._chatProcessMessages.ContainsKey(messageType))
{
sender.Logger.LogDebug("Not implemented chat message type: {0}", messageType);
return;
}
await this._chatProcessMessages[messageType].ProcessMessageAsync(sender, (message, playerName)).ConfigureAwait(true);
}
private ChatMessageType GetMessageType(string message, bool whisper)
{
if (whisper)
{
return ChatMessageType.Whisper;
}
// byte 13: begin message
foreach (var keyValuePair in this._messagePrefixes)
{
if (message.StartsWith(keyValuePair.Key, StringComparison.InvariantCulture))
{
return keyValuePair.Value;
}
}
return ChatMessageType.Normal;
}
///
/// We have to implement a reverse comparer, so that the strings which are longer, come first.
///
private class ReverseComparer : IComparer
{
public int Compare(string? x, string? y)
{
return string.Compare(y, x, StringComparison.InvariantCultureIgnoreCase);
}
}
}