Using DarkRift with MySql and Dapper

Welcome everyone,
In this article, you will learn how to enable your DarkRift standalone server to communicate with a dedicated MySql Server. The process isn’t much complicated.
We’ll also use the « Dapper » library wich is an ORM (Object Relationnal Mapper). If you don’t know what is Dapper, you can check the official website here 

If you don’t know what DarkRift is or works, you can take a look on my entire dedicated tutorial right here : DarkRift Summary

This tutorial assumes that you have the require knowledge on DarkRift Server, MySQL Database and SQL langage. Regarding Dapper, we’ll just make a simple exemple, so, you don’t need to know how to use it.

To make it simple, an ORM is a library wich enables you get a C# instance of an object from a Database Query wich will return a row

This tutorial will just show you the basics of how use MySql and Dapper within a DarkRift plugin. If you want a detailed overview ajout how to organize your project with a standalone darkrift server, just check this article : available soon 

Set up the project

As you know, you need to download the DarkRift Network asset available here : https://assetstore.unity.com/packages/tools/network/darkrift-networking-2-95309
Download the asset and browse it until to find the .zip wich contains DLLs that will be used to create our DarkRift Plugin. Unzip it :

Create the DarkRift.Plugins project in VS

The project will be a Class library. We’ll need to add a reference to the DarkRift Dlls (DarkRift.dll and DarkRift.Server.dll).

After visual studio has finished to create the project, you need to reference the DarkRift libraries.You will need to navigate until unzipped folder to find these files :

After that, we’ll install MySql library and the Dapper library. For that purpose, we’ll use Nuget Package Manager. It will automatically install these libraries for us
We’ll use these 2 packages :

  • Install-Package MySql.Data -Version 8.0.16
  • Install-Package Dapper -Version 1.60.6

Here is how you need to process :

Here we are, we finally have our project ready to be used. We have our project with references to :

  • DarkRift
  • MySql
  • Dapper

The second step consists to set up our database. You can do it locally or use an online database. Choice is yours.

Setup the database

In our tutorial, we just set up a table with a text and send it to a client when he asks for it. Here is the SQL table definition

Create table player_description (
player_id int not null,
description varchar(128)
primary key (player_id));

And add some data into this table

Insert into player_description VALUES (1,'I love what http://materiagame.com is providing to us');<br>
Insert into player_description VALUES (2,'http://materiagame.com has a 2D Destructible tutorial. Feel free to check it');<br>
Insert into player_description VALUES (3,'Thanks you to support and follow me on twitter');

Here is what you should have :

Create and return data to the client

As said, this tutorial assumes that you have already a knowledge of DarkRift. If you need information about how to create a plugin, you can check the official website right here

So, What you need is to wait for a client request that ask you the description of a player. DarkRift works with tag, for the exemple, this request will be bounded to the tag 00000 !

The plugin manager will wait for a client message and will check the tag, if the tag is 00000, so will start to query the database and send the result to the client

Create a PlayerManager class add all these references :

using DarkRift;
using DarkRift.Server;
using Dapper;
using MySql.Data.MySqlClient;

Now, make it ihnerits from Plugin (DarkRift.Server.dll) :

public class PlayerManager : Plugin 

Implements the interface with these 3 functions :

    #region Plugin implementation   
    public override bool ThreadSafe => false;

    public override Version Version => new Version(1, 0, 0);

    public PlayerManager(PluginLoadData pluginLoadData) : base(pluginLoadData)
    {
        //Listen to message
        ClientManager.ClientConnected += OnClientConnected;
    }
    #endregion

You can see that we are listening for a client connection. When a client connects, we’ll listen for his messages.

    #region Connection
    private void OnClientConnected(object sender, ClientConnectedEventArgs e)
    {
        e.Client.MessageReceived += OnClientMessageReceived;
    }

    #endregion

Like this, we are listening all messages from a client. We need to tell wich message this plugin will be in charge of.

    #region Message handle

    private void OnClientMessageReceived(object sender, MessageReceivedEventArgs e)
    {
        switch (e.Tag)
        {
            case 00000:
                SendPlayerDescription(e);
                break;
            default:
                break;
        }
    }

    #endregion

Now, we are quite ready to request the database. We can create the skeleton of the SendPlayerDescription function like this :

    #region Implementation

    public void SendPlayerDescription(MessageReceivedEventArgs e)
    {
        if (e.Tag == 00000)
        {
            using (DarkRiftReader reader = e.GetMessage().GetReader())
            {

            }
        }
    }

    #endregion

Connects and query the database

All the following code will be written into the SendPlayerDescription() function. What are the steps ?

  • Get the Player id from the
  • Connects to the database (
  • Get the row for the specified
  • Map it a an
  • Send this object threw network (Serialize)

To get the player ID, we assume that the message sent by the client has only one parameter wich is an int. Let’s read the value within the incoming darkrift message

int playerId = reader.ReadInt32();

Now, we can connect to the database and write the query :

//Connects to database 

//Build connection string
MySqlConnectionStringBuilder connectionStringBuilder = new MySqlConnectionStringBuilder()
   {
        Server = "mySQLserver",
        Database = "myDB",
        UserID = "myUser",
        Password = "xxxx",
};
                
//Create a connections
MySqlConnection connection = new MySqlConnection(connectionStringBuilder.ConnectionString);
connection.Open();

The connection is made and opened, we now can query the database. First let’s write the query that returns the description for a given player :

//Build the query
string query = string.Format(@"Select player_id playerId, description from player_description where player_id = {0}",playerId);

You can notice that we’ve put an alias to the first field of our result. It’s necessary for Dapper. In deed, when you want to map a result row from a database into a C# object with dapper, it’s important that the result schema has same names that the C# object.

Of course, we can execute the query right now, parse the row and send the result to the client, but what we want is to get the result into an object. And then send the objecta cross the network.

Map the row into an object with Dapper

For that, we need to declare a new C# class into the projet called Player. This class will be hydrated from the result of the SQL query thanks to Dapper.

namespace DarkRift.Plugins
{
    public class Player<br>
    {
        public int playerId;
        public string description;
    }
}

Get back to the SendPlayerDescription() function. Now, juste need to write one line to directly have an instance of the player :

//Get the result under the form of a Player object instead of an array
Player player = connection.QueryFirstOrDefault(query);

Congratulations, you know have your SQL information into a C# object totally filled with information that resides into the player_description table

Send the message (Server)

Now, we can write all this information into a darkrift message. We want that the client have this result into a Player object. So, we have 3 options :

  1. Write each field manually to the message. The Client we’ll have to read manually each field, instantiate a new player and fill fields.
  2. Create PlayerDescriptionResponse wich is a C# class that inherits from IDarkRiftSerializable. Add a property of Player type. In the serialize / Deserialize, write/read fields and fill the Player
  3. The third method, that we’ll use is to make the Player class directly ihnerits from IDarkRift serializable. Like that, you can pass/receive this object directly within/from a darkrift message.

IMPORTANT : For this tutorial, the Player class is defined into the server side. You will need to copy this class into the client to use it when you’ll receive the message from the server.

Here is the updated Player class

 namespace DarkRift.Plugins
 {
    public class Player : IDarkRiftSerializable
    {
         public int playerId;
         public string description;
         public void Deserialize(DeserializeEvent e)
         {
             playerId = e.Reader.ReadInt32();
             description = e.Reader.ReadString();
         }

         public void Serialize(SerializeEvent e)
         {
             e.Writer.Write(playerId);
             e.Writer.Write(description);
         }
     }
}

Finally, get back to the SendPlayerDescription() function and send the message to client like this :

//Create and send the response
using (Message playerInformationMessage = Message.Create(00001, player))
{
    e.Client.SendMessage(playerInformationMessage, SendMode.Reliable);
}

Receive the message (Client)

In your client, you just need to declare again the same Player class as i warned before. (An article about project organization will be written soon with DarkRift 2)
After that, you are able to read your message as following :

using(DarkRiftReader reader = message.GetReader())
{
    //Read data here
    Player player = reader.ReadSerializable();
    //Read more data here
}

You are now ready to work with mysql, dapper and darkrift plugins. This tutorial covers basic, if you need to go deeper, i strongly recommands to learn more about Dapper

Hope it has been helpful, if you have question, use the form below.
Thanks you.