How to Send Network Messages

If you're seeking an intro to developing a basic multiuser virtual world, also look at Multiuser basics and Network mutex

Introduction

There are 2 ways to send network messages.
  • Through channels (recommended).
  • Through the NetworkClient.

For either approach you need to have your plugin also implement the IParkObject.
This will give access to the VastPark Player’s engines which contains the NetworkClient.

1) Channels

Grabbing channels

We recommend using channels as the messages are only sent through that media. Therefore to receive a message one must have the same name and the same configurations to be sent through to the things that are listening to that channel.

In the client plugin (plugins that the VastPark Player runs), it is best to request for a channel when the NetworkClient is connected, which is done by looking out for the ConnectionEstablished event trigger.

1 public void Load()
2 {
3     _ParkEngine.NetworkClient.ConnectionEstablished += new EventHandler<VastPark.Data.EventArg.CustomNetworkMessageArgs>(NetworkClient_ConnectionEstablished);
4 }

Once connection established is triggered, you can request the channel for your plugin.

1 void NetworkClient_ConnectionEstablished(object sender, VastPark.Data.EventArg.CustomNetworkMessageArgs e)
2 {
3     string channelName = "My Plugin Channel";
4     bool reliable = true;
5     bool ordered = true;
6     _ParkEngine.NetworkClient.GetChannel(channelName, reliable, ordered, new TypedAsyncCallback<INetworkChannel>(My_Channel));
7 }

As soon as the channel is provided, it will trigger the call back that you have provided, there you can start looking out for messages that you have received through the MessageReceived event.

1 private void My_Channel(INetworkChannel channel)
2 {
3     _Channel = channel;
4     _Channel.MessageReceived += new Event<string, NetworkMessage>(Channel_MessageReceived);
5 }

Differentiate different message types by the ID property of the message:

 1 void Channel_MessageReceived(object sender, VastPark.Data.EventArg.TypedEventArgs<string, NetworkMessage> e)
 2 {
 3     switch (e.Value2.ID)
 4     {
 5         case 1:
 6             {
 7                 //TODO perform you tasks here
 8                 break;
 9             }
10         case 2:
11             {
12                 //TODO something else here
13                 break;
14             }
15         //etc
16     }
17 }

That’s the basics to grabbing a channel.

Sending Messages

To send a message you need to use the NetworkMessage object from the VastPark.Data project.

There you will need to specify an ID to identify the message you have, and send any information that you may need.
Then choose whom to send it to the message to using your channels. Choose between Broadcast, SendMessage or SendToHost.

 1 public void Use_MyChannel()
 2 {
 3     NetworkMessage message = new NetworkMessage();
 4     message.ID = 1;
 5 
 6     string hello = "Hello World";
 7 
 8     message.WriteInt(hello.Length);
 9     message.WriteString(hello);
10 
11     _Channel.BroadcastMessage(message); //Send message to server plugin and everyone else
12 
13     string senderId = _ParkEngine.NetworkClient.ConnectedClients[0].ClientId;
14 
15     _Channel.SendMessage(senderId, message); //Send the message to the person with id "senderId" 
16     _Channel.SendMessageToHost(message); //Sends to the server only
17 }

You must place the information you want inside the network message in the order that you are planning to extract that information. Think of a NetworkMessage as being similar to a sequentially accessed stream.

Receiving Messages

If you have set up the message received event like this, then messages will passed in.
Try not to do too much work during events handling as it will slow down the framework. If a lot of processing time is needed consider using a queue and another thread to process that queue.

 1 _Channel.MessageReceived += new Event<string, NetworkMessage>(Channel_MessageReceived);
 2 
 3 void Channel_MessageReceived(object sender, VastPark.Data.EventArg.TypedEventArgs<string, NetworkMessage> e)
 4 {
 5     switch (e.Value2.ID)
 6     {
 7         case 1:
 8             {
 9                 //TODO perform you tasks here
10                 NetworkMessage received = e.Value2;
11 
12                 int stringLength = received.ReadInt();
13                 string hello = received.ReadString(stringLength);
14 
15                 // We receive the client alias here but need to know the client Id.
16                 // Lookup the senderId
17                 if (e.Value1 != null)
18                 {
19                     string senderId = (from c in _ParkEngine.NetworkClient.ConnectedClients
20                                        where c.Alias == e.Value1
21                                        select c.ClientId).Single();
22                 }
23 
24                 break;
25             }
26     }
27 }

2) NetworkClient

NetworkClient send/broadcast methods are marked as obsolete and should be avoided as data sent via these methods will become part of the framework's default channels, reserved for IMML state changes. Sending large messages using these methods can cause unwanted delays in state synchronisation.

Receiving Messages

To listen to the default framework messaging channel, in the load method of your plugin you can hook it as follows:

1 public void Load()
2 {
3     _ParkEngine.NetworkClient.CustomNetworkMessageReceived += new EventHandler<VastPark.Data.EventArg.CustomNetworkMessageArgs>(NetworkClient_CustomNetworkMessageReceived);
4 }

The messages will be sent in the CustomNetworkMessageArgs inside the Message property.

 1 void NetworkClient_CustomNetworkMessageReceived(object sender, VastPark.Data.EventArg.CustomNetworkMessageArgs e)
 2 {
 3     switch (e.Message.ID)
 4     {
 5         case 1:
 6             {
 7                 //TODO perform you tasks here
 8 
 9                 break;
10             }
11     }
12 }

Sending Messages

To send a message you need to use the NetworkMessage object from the VastPark.Data project.
There you will need to specify your ID to identify the message you have, and send any information that you may need.
Then choose whom to send it to the message to using your channels. Choose between Broadcast, SendMessage or SendToHost.

 1 public void SendMessage()
 2 {
 3     NetworkMessage message = new NetworkMessage();
 4     message.ID = 1;
 5 
 6     string hello = "Hello World";
 7 
 8     message.WriteInt(hello.Length);
 9     message.WriteString(hello);
10 
11     _ParkEngine.NetworkClient.SendMessageToHost(message); //Sends to the server and triggers the message to the server plugin
12     _ParkEngine.NetworkClient.BroadcastMessage(message); //Send message to server plugin and everyone else
13 
14     string senderId = _ParkEngine.NetworkClient.ConnectedClients[0].ClientId;
15 
16     _ParkEngine.NetworkClient.SendMessage(senderId, message); //Send the message to the person who has got it
17 }

You must place the information you want inside the network message in the order that you are planning to extract that information.