Mud Engine + Server running on Mac OS X

As of tonight, the Mud Engine has been tested and runs on Macs running OS X. I was even able to wire up the server and get a OS X server running with the game.

Thanks to how the server was refactored into the adapter pattern I adopted a couple of weeks ago, it took very little code to wire up a OS X based server.

The code

class MainClass
{
    public static void Main(string[] args)
    {
        SetupMessageBrokering ();

        var bootstrap = new Bootstrap ();
        bool startupCompleted = false;
        bootstrap.Initialize ((game, server) =>
        {
            // Start the game loop.
            while(game.IsRunning)
            {
                if (!startupCompleted)
                {
                    startupCompleted = true;
                }

                Thread.Sleep(1);
            }
        });

        while(!startupCompleted)
        {
            Thread.Sleep (1);
        }
    }

    static void SetupMessageBrokering()
    {
        MessageBrokerFactory.Instance.Subscribe<InfoMessage>(
            (msg, subscription) => Console.WriteLine(msg.Content));

        MessageBrokerFactory.Instance.Subscribe<GameMessage>(
            (msg, subscription) => Console.WriteLine(msg.Content));

        MessageBrokerFactory.Instance.Subscribe<PlayerCreatedMessage>(
            (msg, sub) => Console.WriteLine("Player connected."));

        MessageBrokerFactory.Instance.Subscribe<PlayerDeletionMessage>(
            (msg, sub) =>
        {
            Console.WriteLine("Player disconnected.");
        });
    }
}

This code should look almost identical to the source previously posted showing the Mud Engine server running on Windows. The only difference is that I abstracted the code that can be shared across the two platforms into a bootstrap. The shared code is stuff like configuring the server and game, setting up the game and adapter and starting the game.

As development of the engine continues, I will regularly check and make sure it builds on OS X. The engine itself and its server should always run cross-platform without any issues.

I'm not sure yet what I am going to do in regards to the designer tools. Initially I was going to write it as a XAML app for Windows. Considering that the engine can now run on OS X (and I will be testing it on Linux soon), I might reconsider and look at a more cross-platform UI approach. Perhaps that would be a good excuse for me to pick up the new cross-platform ASP.Net MVC 6 stuff Microsoft is doing, and build a cross-platform self-contained web application for the designer.

Anyway, I wanted to share the progress on my cross-plat goals. At the moment, everything seems to be working just fine between Windows and OS X.

The new configurable Mud Engine Server Adapter

Back in May I posted about how you could configure the mud server for use with the Mud Engine. Since then, I have built out an implementation of the Adapter pattern. With that, I wanted to demonstrate how you would startup the server with the engine, and configure it.

Previously in the Mud Engine

In the last iteration of my configuration setup, you had to implement the abstract ServerBootstrap class, and then build out an implementation of IServerConfiguration. The bootstrap implementation looked something like this.

public class DefaultServerBootstrap : ServerBootstrap
{
    protected override void Run()
    {
        this.Server.GetCurrentGame()
            .NotificationCenter
            .Subscribe<ServerMessage>((msg, sub) => 
                Console.Write(msg.Content));

         while (this.Server.Status != ServerStatus.Stopped)
        {
            Thread.Sleep(100);
        }
    }

    protected override void RegisterAssemblies()
    {
        base.RegisterAssemblies();
    }

    protected override void ConfigureServices()
    {
    }

    protected override IServerConfiguration CreateServerConfiguration()
    {
        return new ServerConfiguration();
    }

    protected override IServer CreateServer()
    {
        var server = new Server();
        server.PlayerConnected += this.ExecuteInitialCommand;
        return server;
    }

    protected override IGame CreateGame()
    {
        return new DefaultGame();
    }

    protected override IInputCommand InitialConnectionCommand()
    {
        returnnew PlayerLoginCommand();
    }

    protected override void RegisterAllowedSecurityRoles(IEnumerable<ISecurityRole> roles)
    {
    }
}

Then in the application startup, you had to setup the bootstrap.

public static void Main(string[] args)
{
    var bootstrap = new DefaultServerBootstrap();    
    Task bootstrapTask = bootstrap.Initialize();
    bootstrapTask.Wait();
}

This was the minimum that had to be done in order to start the game with a server. There were several issues with this approach, one of which is violating SRP. The bootstrap does a lot of different things that aren't even related to the server. It defines the initial command, creates a player, and creates the game. None of which are specific to the server. These actions can be applicable in a single-player game as well.

The other thing that the bootstrap does is configures any services, and register security roles with the services. Gross. The server startup should be free of IoC dependency injection setup goo. So I set out to fix that with the new Mud Engine Adapters.

Setting up a server with adapters

Now that the server has been migrated over to use the adapter architecture, it's much more straight-forward to get a server running. Previously, the server owned the game. Now, the game owns the server - it just doesn't know it.

To start up the game, and give it a server, we do this.

static void Main(string[] args)
{        
    var serverConfig = new ServerConfiguration();
    IServer server = new WindowsServer(new TestPlayerFactory(), new ConnectionFactory(), serverConfig);

    var gameConfig = new GameConfiguration();
    gameConfig.UseAdapter(server);  

    var game = new MudGame();
    game.Configure(gameConfig);

    Task gameStartTask = game.StartAsync();
    gameStartTask.Wait();
}

In the code above, we create a serverconfiguration. Then we create a WindowsServer instance, giving it a couple of factories and our config. Next we we create a GameConfiguration and register our WindowsServer with the game config. When we call game.Configure(gameConfig), the game will consume the WindowsServer adapter and automatically configure the server using the ServerConfiguration.

Lastly, we start the game calling game.StartAsync(). This initialize and run all of the registered adapters that the game has. In our case, it initializes and runs the WindowsServer. At this point, the WindowsServer is running and can accept incoming client connections.

There is some flexability when it comes to configuring adapters. Each adapter can either skip configuration all-together, or opt into configuration by requiring a configuration class. This can be any class that implements the IConfiguration interface. Taking this approach allows each adapter to have their own config that can be tailored to what they want to expose. In the case of Server Configuration, there is quiet a bit we can do with it. For instance:

var serverConfig = new ServerConfiguration();
serverConfig.OnServerStartup = (context) => 
    Console.WriteLine($"Server running on port {context.Server.RunningPort}");

That code registers a callback that will be invoked when the server is starting. In this example, we just lookup the port the server is running on and write it out to the console. You can do more then just that however.

static void Main(string[] args)
{        
    var serverConfig = new ServerConfiguration();
    serverConfig.OnServerStartup = (context) =>
    {
        context.ListeningSocket.BeginAccept(
            new AsyncCallback(Program.HandleClientConnection), context.ListeningSocket);
        context.SetServerState(ServerStatus.Running);
        context.IsHandled = true;
    };

    IServer server = new WindowsServer(new TestPlayerFactory(), new ConnectionFactory(), serverConfig);

    var gameConfig = new GameConfiguration();
    gameConfig.UseAdapter(server);

    var game = new MudGame();
    game.Configure(gameConfig);

    Task gameStartTask = game.StartAsync();
    gameStartTask.Wait();
}

private static void HandleClientConnection(IAsyncResult result)
{
    Socket server = (Socket)result.AsyncState;
    Socket clientConnection = server.EndAccept(result);

    // Fetch the next incoming connection.
    server.BeginAccept(new AsyncCallback(HandleClientConnection), server);

    // Create player character here.
}

In this example, we used both the WindowsServer and it's Socket to completely replace the way incoming connections are handled. We're not replacing how client communication between the server and client are handled (that is planned) but allowing users to define custom server behavior without reimplementing IServer. At the end of the OnServerStartup callback, we set IsHandled to true, which tells the server to stop using its internal startup and rely on the custom logic being defined.

There are more things you can do, such as intercepting the shutdown of the server, client connections, disconnects and more.

Sharing information across adapters

The server publishes out messages that you can intercept and react to as well. An example is this:

static void Main(string[] args)
{
    SetupMessageBrokering();

    var serverConfig = new ServerConfiguration();
    IServer server = new WindowsServer(new TestPlayerFactory(), new ConnectionFactory(), serverConfig);

    var gameConfig = new GameConfiguration();
    gameConfig.UseAdapter(server);

    var game = new MudGame();
    game.Configure(gameConfig);

    Task gameStartTask = game.StartAsync();
    gameStartTask.Wait();
}

static void SetupMessageBrokering()
{
    MessageBrokerFactory.Instance.Subscribe<InfoMessage>(
        (msg, subscription) => Console.WriteLine(msg.Content));

    MessageBrokerFactory.Instance.Subscribe<GameMessage>(
        (msg, subscription) => Console.WriteLine(msg.Content));

    MessageBrokerFactory.Instance.Subscribe<PlayerCreatedMessage>(
        (msg, sub) => Console.WriteLine("Player connected."));

    MessageBrokerFactory.Instance.Subscribe<PlayerDeletionMessage>(
        (msg, sub) =>
        {
            Console.WriteLine("Player disconnected.");
        });
}

The first thing we do is subscribe, via the MessageBroker, to a series of messages that can be published by other objects. In this scenario, the WindowsServer will publish messages that are InfoMessage, PlayerCreatedMessage and PlayerDeletionMessage. The MudGame will publish GameMessage notifications. This looks like this when the server is running and has accepted several connections, and had a few disconnects.

The flexability given now with adapters and their custom configurators will make it easy to get up and running, and still provide you with a lot of flexability when you want to do more advanced things.

As always you can replace the IServer or IServerConfiguration implementations with your own all together. Since IServer inherits from IAdapter your custom implementation can plug straight into the game using the game.UseAdapter(customServer) call.

Handling what is missing

The original implementation shown at the start of this post had some other things being done. It handled the setup of security and commanding. That responsibility will be moved to additional adapters, which will run independent of the server and game. They can subscribe to messages sent from the server and react to them, launching the initial login command and handling security without knowing that the server even exists.

var gameConfig = new GameConfiguration();
gameConfig.UseAdapter(new WindowsServer());
gameConfig.UseAdapter(new CommandManager());
gameConfig.UseAdapter(new SecurityBroker());
gameConfig.UseAdapter(new WorldManager());

var game = new MudGame();
game.Configure(gameConfig);

Task gameStartTask = game.StartAsync();

Each one of the adapters shown above have not been written yet; they are coming. When they are ready, they will share the same level of flexability as the server, using configuration objects that you can intercept and interact with.

There is a lot of other new stuff happening in the engine that won't fit into this post, like a new home on GitHub (more on that in a different post), character APIs and real usage documentation.

More coming soon!

Localization Support for ValidatableBase

Localization Support

The included Validation Attributes now all support localization, allowing your failure messages to be presented to the user in the native language for global applications. In order to provide this in a cross-platform manor (iOS, Android and Windows), localization support must be handled with a couple levels of indirection.

Without localization, you would manually specify the FailureMessage like this:

[ValidateObjectHasValue(
    FailureMessage = "Email address must not be blank.",
    ValidationMessageType = typeof(ValidationErrorMessage))]
public string Email
{
    get
    {
        return this.email;
    }

    set
    {
        this.email = value;
        this.OnPropertyChanged("Email");
    }
}

Localization is done by specifying a localization key on your validation rules and omitting the FailureMessage property assignment like the following.

[ValidateObjectHasValue(
    LocalizationKey = "User-Email-Validation-Failure-Cannot-be-blank",
    ValidationMessageType = typeof(ValidationErrorMessage))]
public string Email
{
    get
    {
        return this.email;
    }

    set
    {
        this.email = value;
        this.OnPropertyChanged("Email");
    }
}

When validation is performed, and the Email property is null, a localized failure message will be assigned to the FailureMessage property.

In order to facilitate this, the validation rules fetch an implementation of IValidationLocalizationService from a new Factory, the ValidationLocalizationFactory. The API ships with a Windows App Store supported localization service in the Universal App Shared project.

The factory must provide this service to the validation rules. In order to do that, you must initialize the factory. This is demonstrated in the sample projects as well, in the App.Xaml.cs file.

public App()
{
    this.InitializeComponent();
    this.Suspending += this.OnSuspending;

    ValidationLocalizationFactory.Initialize<ValidationLocalizationService>();
}

The factory is initialized with our Windows App Store version of the localization service included in the sample project. The validation rules will use this service any time that it needs to fetch a localized string.

Another feature of the localization support are fallback messages. While you are developing the application, you often don't have all of the localization done. You can assign a value to both FailureMessage and LocalizationKey. The validation rule will try to fetch a localized string and if none exist, continue to use the specified FailureMessage. If it finds a localized string, it replaces the fallback value with the localized string for you.

The following demonstrates this:

[ValidateObjectHasValue(
    FailureMessage = "Email address can not be blank.", /* fallback if localization does not exist for the key yet */
    LocalizationKey = "User-Email-Validation-Failure-Cannot-be-blank",
    ValidationMessageType = typeof(ValidationErrorMessage))]
public string Email
{
    get
    {
        return this.email;
    }

    set
    {
        this.email = value;
        this.OnPropertyChanged("Email");
    }
}

You can create a custom implementation of IValidationLocalizationService for iOS and Android apps as well. Just initialize the ValidationLocalizationFactory with the Service type for each platform. This allows you to use localized text across all platforms that your app can run on, without making any changes to your models or building custom validation rules per-platform.

Check out the latest build over on the GitHub Repository.

Good-bye OnPropertyChanged. Hello BindableProperty

One of the most annoying things with XAML binding in WPF and Windows App Store apps is the need to raise a property changed notification to the user interface. Typically, you would abstract the actual property changed notification in to a base class like this:

public class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void SetProperty<T>(ref T oldValue, T newValue, [CallerMemberName] string property = "")
    {
        if (object.Equals(oldValue, newValue))
        {
            return;
        }

        oldValue = newValue;
        this.OnPropertyChanged(property);
    }

    protected virtual void OnPropertyChanged(string property)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(property));
        }
    }
}

This at least prevents you from having to implement INotifyPropertyChanged on every one of your models. The issue however is that you still need to raise the event. In order to do so, you would invoke the base class' OnPropertyChanged method.

public class User : BindableBase
{
    private string firstName;

    private string lastName;

    public string FirstName
    {
        get
        {
            return this.firstName;
        }
        set
        {
            this.SetProperty(ref this.firstName, value);
        }
    }

    public string LastName
    {
        get
        {
            return this.lastName;
        }

        set
        {
            this.SetProperty(ref this.lastName, value);
        }
    }
}

The boiler plate code here gets really monotonous when you have a project with more than a handful of models. Luckily, Roslyn now has Initializer support for Auto-Properties..

With Auto-Property Initializers, we can build a wrapper around the actual property and bind to the value our wrapper holds. To demonstrate, we will create a simple wrapper. There will be a generic and a non-generic flavor. The non-generic provides a static method for constructing a generic wrapper. We will call this wrapper BindableProperty.

Generic Property Wrapper

public class BindableProperty<T> : BindableBase
{
    private T value;

    public BindableProperty(T value, [CallerMemberName] string propertyName = "")
    {
        this.value = value;
        this.Name = propertyName;
    }

    public BindableProperty([CallerMemberName] string propertyName = "")
    {
        this.value = default(T);
        this.Name = propertyName;
    }

    public T Value
    {
        get
        {
            return this.value;
        }

        set
        {
            this.SetProperty(ref this.value, value);
        }
    }

    public string Name { get; private set; }

    public static BindableProperty<T> Prepare(T value, [CallerMemberName] string propertyName = "")
    {
        return new BindableProperty<T>(value, propertyName);
    }

    public static BindableProperty<T> Prepare([CallerMemberName] string propertyName = "")
    {
        return new BindableProperty<T>(default(T), propertyName);
    }
}

Non-generic static class for coonstruction

public static class BindableProperty
{
    public static BindableProperty<T> Prepare<T>([CallerMemberName] string propertyName = "")
    {
        return new BindableProperty<T>(default(T), propertyName);
    }
}

You can see the BindableProperty object still has a private backing field and a property setter that handles the property changed event. The difference however is that this is the only place this code needs to ever exist now.

With our new BindableProperty object, let's re-write our User.

public class User
{
    public BindableProperty<string> FirstName { get; set; } = BindableProperty.Prepare<string>();

    public BindableProperty<string> LastName { get; set; } = BindableProperty.Prepare<string>();
}

We now have properties in our model that can be data-bound to and push change notifications back to the UI. We could even provide an initial value for the properties if we wanted to.

public class User
{
    public BindableProperty<string> FirstName { get; set; } = BindableProperty.Prepare<string>(string.Empty);

    public BindableProperty<string> LastName { get; set; } = BindableProperty.Prepare<string>("Stevenson");
}

Now we can create a view model real-quick for our view.

public class NewUserViewModel : ICommand
{
    public User NewUser { get; set; } = new User();

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public async void Execute(object parameter)
    {
        if (string.IsNullOrEmpty(this.NewUser.FirstName.Value) ||
            string.IsNullOrEmpty(this.NewUser.LastName.Value))
        {
            var dlg = new MessageDialog("User information is invalid");
            await dlg.ShowAsync();
        }
    }
}

In order to execute properly, the FirstName and LastName properties need to have their Value property checked. If the Value property is null, we show a dialog. Having to check the Value property is an extra step that you wouldn't normally need to take, but one extra 'dot' is a lot less than having to write all the OnPropertyChanged boiler plate code.

Now for our view, we just wire up a quick simple user entry form. The TextBoxes are bound to the Value property in each of the User's BindableProperty properties.

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="First name" />
        <TextBox Text="{Binding Path=NewUser.FirstName.Value}" />
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Last name" />
        <TextBox Text="{Binding Path=NewUser.LastName.Valuey}" />
    </StackPanel>

    <Button Command="{Binding }"
            Content="Create." />
</StackPanel>

This is going to make your models a lot cleaner and speed up the amount of time it takes to create property changed based objects.

Building an Exception Factory

If you write a lot of code that takes dependencies in a method or constructor, you'll find that you write a lot of null checking like this:

public DefaultGame(ILoggingService loggingService, IWorldService worldService)
{
    if (loggingService == null)
    {
        throw new ArgumentNullException("loggingService", "Logging Service must not be null!");
    }
    else if (worldService == null)
    {
        throw new ArgumentNullException("worldService", "World Service must not be null!");
    }

    this.loggingService = loggingService;
    this.worldService = worldService;
}

Depending on the number of dependencies, this tends to bloat methods with more safety checks than actual code. I wanted to resolve this, and did so with a factory.

The factory needed to satisfy a few things.

  • Instance exceptions
  • Support stashing custom data in to the exceptions
  • Only throw if a given condition was met
  • Allow a callback if the conditions are not met (meaning no exception will be thrown)

Turns out this was pretty easy to implement. The end product, in its simplest form looks like this:

public DefaultGame(ILoggingService loggingService, IWorldService worldService)
{
    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(loggingService == null);
    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(worldService == null);

    this.loggingService = loggingService;
    this.worldService = worldService;
}

You can also invoke a callback, and provide a custom message.

public DefaultGame(ILoggingService loggingService, IWorldService worldService)
{
    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(loggingService == null, "Logging Service must not be null!")
        .ElseDo(() => this.loggingService = loggingService);

    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(worldService == null, "World Service must not be null!")
        .ElseDo(() => this.worldService = worldService);
}

If you need to do something more complex with your conditional check, you use a Func< bool>

ExceptionFactory
    .ThrowExceptionIf< Exception>(
        () =>
        {
            this.Worlds = worldService.GetAllWorlds();
            return this.Worlds.Any();
        },
        "An empty world can not be used!"));

It also supports providing a custom exception factory method for use. Since some exceptions have additional parameters in the constructor, this can be really useful.

ExceptionFactory
    .ThrowExceptionIf< ArgumentNullException>(
        worldService == null,
        () => new ArgumentNullException("worldService", "World Service must not be null!"));

We can also pass custom data in to the exception if we want.

ExceptionFactory
    .ThrowExceptionIf< ArgumentNullException>(
        worldService == null,
        () => new ArgumentNullException("worldService", "World Service must not be null!"),
        new KeyValuePair< string, string>("Member", "DefaultGame"),
        new KeyValuePair< string, string>("MemberType", "Constructor"));

So how does the insides work? Let's take a look

The Factory

There are a total of four factory methods.

  • ThrowExceptionIf< TException>(Func< bool> predicate, string message = null, params KeyValuePair< string, string>[] data);
  • ThrowExceptionIf< TException>(Func< bool> predicate, Func< TException> exception, params KeyValuePair< string, string>[] data)
  • ThrowExceptionIf< TException>(bool condition, string message = null, params KeyValuePair< string, string>[] data)
  • ThrowExceptionIf< TException>(bool condition, Func< TException> exception, params KeyValuePair< string, string>[] data)

and one last method for adding data to the exception

AddExceptionData(Exception exception, params KeyValuePair< string, string>[] data)

Since we can build this in an overloaded fashion, we will just build the most complex method out, then let the rest of them piggy back on top of it.

public static ExceptionFactoryResult ThrowExceptionIf< TException>(bool condition, Func< TException> exception, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    if (condition)
    {
        return new ExceptionFactoryResult();
    }

    TException exceptionToThrow = exception();
    AddExceptionData(exceptionToThrow, data);

    throw exceptionToThrow;
}

This method is really straight forward, it requires a bool value to indicate if this exception must be instanced and thrown or not. If the condition is false, then we go ahead and invoke the Func< TException> delegate. This returns the exception that we are to throw.

Next we take the optional exception data parameter and pass it to an AddExceptionData method. That method will iterate over the param data and add it to the exception. We then finally throw the exception. Really straight forward.

The AddExceptionData method looks like this:

public static void AddExceptionData(Exception exception, params KeyValuePair< string, string>[] data)
{
    foreach (var exceptionData in data)
    {
        exception.Data.Add(exceptionData.Key, exceptionData.Value);
    }
}

Now we can build out our overloads. The second most complex one is really easy to write. We just pass a delegate in that instances a new exception using the Activator class.

public static ExceptionFactoryResult ThrowExceptionIf< TException>(bool condition, string message = null, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    return ThrowExceptionIf< TException>(
        condition,
        () => (TException)Activator.CreateInstance(typeof(TException), message),
        data);
}

Next, we will provide support for delegate predicates.

public static ExceptionFactoryResult ThrowExceptionIf< TException>(Func< bool> predicate, Func< TException> exception, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    return ThrowExceptionIf< TException>(predicate(), exception, character, data);
}

public static ExceptionFactoryResult ThrowExceptionIf< TException>(Func< bool> predicate, string message = null, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    return ThrowExceptionIf< TException>(predicate(), message, character, data);
}

The last thing we need to do is support the method callbacks. This is done using the ExceptionFactoryResult class that all of our factory methods return. This class has nothing more than a simple method that takes an Action and invokes it.

public class ExceptionFactoryResult
{
    public void ElseDo(Action callback)
    {
        callback();
    }
}

That's all there is to it!