Messaging in Mud Designer
One of the things that bugged me with the previous version of the Mud Designer was how I had essentially hard-coded the encoding of the text directly in to the flow of transfering the data back and forth between the user and the server. The old version of the engine would send content directly to the user like this:
player.SendMessage("What is your username, adventurer? ", false);
and the SendMessage
looked like:
public override void SendMessage(string message, bool newLine = true)
{
// When printing properties that don't have values, they'll
// be null.
if (message == null)
return;
if (newLine && !lastMessageHadNewLine)
message = message.Insert(0, System.Environment.NewLine);
if (newLine)
{
message += System.Environment.NewLine;
lastMessageHadNewLine = true;
}
else
this.lastMessageHadNewLine = false;
// Make sure we are still connected
try
{
if (IsConnected)
Connection.Send(new ASCIIEncoding().GetBytes(message));
}
catch (Exception ex)
{
// No connection was made, so make sure we clean up
if (!IsConnected)
Disconnect();
}
}
So, as you can see the formatting of the content sent to the player was pretty static. If you wanted to change how the text was formatted, you had to modify this one method. If you wanted to have multiple types of formatting it was almost impossible because you would not know what the content of the message was once it was within the SendMessage
method. You only know that there is text that must be sent. This was changed in the re-write. Now, all messages are wrapped within an IMessage
object. The object must have a property called Message
which contains the actual message and a method called FormatMessage()
. The interface looks like this:
public interface IMessage
{
/// < summary>
/// Gets or sets the message.
/// < /summary>
string Message { get; set; }
/// < summary>
/// Formats the message.
/// < /summary>
/// < returns>Returns a formatted message.</returns>
string FormatMessage();
}
Why is this a good thing? Now you can customize how you want your message to be sent to the player. For instance, I have an IState
object that handles the users login. The state renders both a welcome message to the user along with a prompt to enter the users name. I can now format both messages differently, by creating two different IMessage
objects. One for showing information and one for asking for input.
this.connectedPlayer.Send(new InformationalMessage("Invalid username/password specified."));
this.currentState = CurrentState.FetchUserName;
this.connectedPlayer.Send(new InputMessage("Please enter your user name"));
The above code outputs the following to the players console:
Invalid username/password specified.
Please enter your user name >:
The first IMessage
type is implemented with out any formatting. It just takes the message and appends a new line to the end of it.
public class InformationalMessage : IMessage
{
public InformationalMessage(string message)
{
this.Message = message;
}
/// < summary>
/// Gets or sets the message.
/// < /summary>
public string Message { get; set; }
/// < summary>
/// Formats the message.
/// < /summary>
public string FormatMessage()
{
return this.Message += Environment.NewLine;
}
}
The second one, InputMessage
formats the message by appending a >:
to the end of the message. This indicates that the user must enter a command in order to continue.
public class InputMessage : IMessage
{
/// < summary>
/// Initializes a new instance of the <see data-preserve-html-node="true" cref="InputMessage"/> class.
/// < /summary>
/// < param name="message">The message.</param>
public InputMessage(string message)
{
this.Message = message;
}
/// < summary>
/// Gets or sets the message.
/// < /summary>
public string Message { get; set; }
/// < summary>
/// Formats the message.
/// < /summary>
public string FormatMessage()
{
return string.Format("{0}>: ", this.Message);
}
}
By requiring all of the methods within the engine that pass messages around, to be supplied with an IMessage
implementation, the engine can display data differently to the user based off of what the context of that data is. This should make presenting content more flexible in the engine going forward.