Tutorial for using Kaleta.Network distribution library



Imagine this scenario:

We would like to develop a network game where there are 2 players. Each player owns a tank. This tank should be visible and interactive in game with other tanks of other players.

The standard way to go is to notify allways all players(clients) of changing of some properties of the tank such as speed, rotation, e.t.c..
You could do this for instance in an update loop by implementing a network-update logic for each property of tank.
But if there are lots of objects with lots of properties you want to distribute to all clients, this would be a messy solution.

The other way is to register the tank as Distributable Object. Then you say which properties you want to synchronize (distribute) with all other clients.

With the distribution library you could do this like this:


public class Tank: DistributableObject
    {
        private DistributableProperty<int> _x;
        private DistributableProperty<int> _y;
        
        public Tank()
        {
            _x= DistributableProperty<int>.Register("X", this);
            _y= DistributableProperty<int>.Register("Y", this);
        }

        [Distribute]
        public int X
        {
            get { return _x.GetValue(); }
            set {  _x.SetValue(value); }
        }

        [Distribute]
        public int Y
        {
            get { return _y.GetValue(); }
            set { _y.SetValue(value); }
        }
}

As you can see, our game object Tank derives from DistributableObject. Then we register what properties we want to synchronize with all other clients.

So how can we use this Tank so that all clients will be notified about it?

Simply:
First we create the tank:

Tank tank = DistributionSession.CreateObject<Tank>();

this will notify me and all other clients about this new object.

Now if we want to change some of the properies of tank we just use ordinary .NET setters/getters:

tank.X = 100;
tank.Y = 120;

That's it!

So everywhere in your program you just set/get properties from the distributed object and you get that what every client does.

The logic in it is that if you set the distributed property, first the new value will be sent to server. The server keeps track of all distributed objects, you dont have to worry.
After server gets notified about the new value, it resends the new value to all clients.
Until then the clients use old value.


To use the distribution you have of course to start server/client.
This library uses the Ligren network library for networking.

Of course you should update the network once in a while. In a game loop, you will do this in the Update method:

//update client:
DistributionSession.ClientUpdate();

//Optional: if we are server, update it also:
if (DistributionSession.Server != null)
                DistributionSession.ServerUpdate();


To set up the distribution, we have to attach the client/server to the DistributionSession first.

We do this like this:


//This is Lidgren stuff:
NetConfiguration clientConfig = new NetConfiguration(this.GetType().Name);
            NetClient client = new NetClient(clientConfig);
            client.Start();
            client.DiscoverKnownServer("localhost", 666);

//This is Distribution stuff:
DistributionSession.Initialize(client, 
                new Type[] { typeof(Tank) });



The DistributionSession.Initialize will attach the running client and register the type Tank for distribution purposes.
That's it.

If we want to have server, we do it in a similar way:

//This is Lidgren stuff:
NetConfiguration serverConfig = new NetConfiguration(this.GetType().Name);
            serverConfig.Port = 666;
            serverConfig.MaxConnections = 4;
            NetServer server = new NetServer(serverConfig);
            server.Start();

//This is Distribution stuff:
            DistributionSession.Initialize(server,
                new Type[] { typeof(Tank) });


We could start the client and server in the same application.

Now, if we want to get to the distributed objects, we access them through the DistributionSession.DistributableObjects dictionary.

This dictionary is synchronized with server and all clients.
To draw all tanks we just do this:


foreach (DistributableObject obj in DistributionSession.DistributableObjects.Values)
            {
                if (obj is Tank)
//draw the tank...
                    
            }

One more thing: if you connect to a distribution session, which already has some distributable objects, you will automatically download those objects, so you will have an updated distribution session from start.

There are far more options with the Distribution library, but that's in next tutorial AdvancedTutorial.
There is a complete sample to download in the Releases section for those who are interested.

Last edited Oct 16, 2009 at 8:25 AM by Kaleta, version 9

Comments

No comments yet.