Skip to content
This repository has been archived by the owner on Aug 15, 2022. It is now read-only.

Network Messages

Brent Farris edited this page Apr 12, 2020 · 11 revisions
Directory Previous Next
Directory Getting Started With Alloy Network Message Interpreters

Network messages are the very core of Forge Networking in this latest revision.

Creating a message and interpreter

To create a message and an interpreter automatically use the right click context menu Create -> Forge Networking -> Network Message Script.

image

After you select the network message script option you will be presented with the following dialog window.

image

Message name: This will be the C# class name for your script. The word Message is automatically appended to the end of the message name, so there is no need for you to type that as part of the name.

Interpret on server: If this checkbox is enabled, then this message is allowed to be interpreted on the server. This means if a client sends this message to the server, it will execute its behavior. If you do not check this box, then the server will ignore this message if it is received.

Interpret on client: If this checkbox is enabled, then this message is allowed to be interpreted on the client. This means if a server sends this message to the client, it will execute its behavior. If you do not check this box, then the client will ignore this message if it is received.

Singleton Interpreter: This is the default and probably isn't something you would want to turn off unless you are an advanced developer in need of creating new instances of this interpreter for the message to be read by. By turning this on, you will still be able to new up the class (for unit tests and any other reasons), so don't worry.

Note about singletons: I am by no means a fan of singletons, the only singletons that make any sense are ones that contain no state and are supplied arguments to work with, basically turning them into static functions/classes.

How the message works

The message is mainly a data object, that is to say it is a class that's primary role is to house some properties that describe the message. You see that the message is decorated with some information like EngineMessageContract but we'll cover that more in detail in the advanced info section of this page. Below is an example of a message which was created using the name Chat and was selected to be interpreted both on the client. Note that I've filled out some dummy data for this sample. Also note that the value 6 is chosen at random for EngineMessageContract in this sample.

[EngineMessageContract(6, typeof(Chat))]
public class ChatMessage : ForgeMessage
{
	public string Name { get; set; }
	public string Text { get; set; }

	public override IMessageInterpreter Interpreter => ChatInterpreter.Instance;

	public override void Deserialize(BMSByte buffer)
	{
		Name = ForgeSerializer.Instance.Deserialize<string>(buffer);
		Text = ForgeSerializer.Instance.Deserialize<string>(buffer);
	}

	public override void Serialize(BMSByte buffer)
	{
		ForgeSerializer.Instance.Serialize(Name, buffer);
		ForgeSerializer.Instance.Serialize(Text, buffer);
	}
}

Let's start by going over the properties. We have 2 properties Name and Text (both happen to be strings in this case, but you can use any data type you wish). These fields do not need to be filled out when you create the message, but need to be filled out before you send the message across the network. This is the data that you are wishing to send, this could be player position (Vector3), some sort of identifier (int), etc.

Next you will notice the Interpreter for the message, this is the class that will be handling this message when it is received on the network. We will go into more details on what the interpreter is and does in the Network Message Interpreters documentation page.

Now on to the Deserialize and the Serialize functions respectively. It is important that you take note of the order that you serialize and deserialize your message data. These functions are the place where you can write custom code to compress your data (say you want to send less data over the wire) or you can send the data raw. You could even choose not to send specific fields of the message and instead use that field for other purposes to describe how to compress the message for example. Again, the order does matter. Make sure if you Serialize first the Name field and then the Text field, that you Deserialize them in that exact same order Name then Text just as you can see in the sample.

Lastly you see the ForgeSerializer come into play here for serialization and deserialization. We will go more into details about the ForgeSerializer in the Serialization Strategy documentation page. For now, just know that it is responsible for knowing how to take a specific data type and write it to bytes and also how to take a series of bytes and convert them back into a specific data type.

Sending a message

There is a fancy thing called a NetworkMediator that takes on the responsibility of sending your messages. The easiest way to get this mediator from anywhere is to get the reference to the ForgeEngineFacade. The engine facade is a way of interfacing with the larger Forge code from within your engine code (thus "Engine" in it's name). You typically can find a reference to this object by doing GameObject.FindObjectOfType<ForgeEngineFacade>(); from within your code. With a reference to this object you can send your message.

ChatMessage m = new ChatMessage
{
	Name = "Forge",
	Text = "Hello World!"
};
IEngineFacade engine = GameObject.FindObjectOfType<ForgeEngineFacade>();
ISocket mySocket = engine.NetworkMediator.SocketFacade.ManagedSocket;
engine.NetworkMediator.SendReliableMessage(m, mySocket.EndPoint);

Note: Please also review Message Pools

Troubleshoot

What if 2 of my messages have the same message code (6 in our sample)?

  1. In Unity, go to Window -> Forge -> Networking Editor
  2. Click on Message Checker
  3. This window will tell you if you have any message conflicts
  4. Look at the top of the window, it will tell you the next available message code that is free
  5. Go to one of the conflicting message codes and change the number manually to the number you see in the window

Advanced info

You may have come to this section of the documentation to learn about what the EngineMessageContract is and how it works. Before continuing I would like to point out there are many different kinds of attributes that describe message contracts. You can view the code that defines all there attributes here.

The message contract attribute is responsible for separating out the messages by a given id (6 in our sample above). When the message comes across the network there has to be a way of identifying what type of message it is, this code is responsible for looking up what type to create based on the identifier.

The reason there are many attributes is because we want to make sure that the underlying Forge Networking code has the ability to create some pre-made messages for the system to operate. So that we don't overwrite developers' identifiers, we have made it so that you, the developer, will use EngineMessageContractAttribute to describe your messages. This basically is the negative number space, while Forge will occupy the positive number space (so you get 1 extra message than the Forge number space).

If this is all confusing, don't worry, you can come back to this at a later time, there is no need for you to worry about understanding this portion right now.

Message template files

The template system in Forge Alloy is much less a system and much more a file selection and modifying it's contents. The file templates can be located in the Assets/ForgeNetworking/Editor/Resources/ForgeNetworking/Templates folder. As it relates to Messages, you'll see a MessageTemplate.txt file and a MessageTemplateSingleton.txt. Based on if you select for the interpreter to be a singleton or not will select which of the two templates to use.


Directory Previous Next
Directory Getting Started With Alloy Network Message Interpreters

Home

Getting Started
Network Contract Wizard (NCW)
Network Object
Remote Procedure Calls (RPCs)
Unity Integration
Basic Network Samples
Scene Navigation
NetWorker
Master Server
Web Server
Netcoding Design Patterns
Troubleshooting
Miscellaneous
Forge Networking Alloy
Steamworks
Clone this wiki locally