Skip to main content

Networking

Cubivox is a heavily online multiplayer game that requires communication between the server and clients. The Cubivox Core provides an easy and efficient ways for mods to communicate between the server and clients. This networking solution is known as Transports.

Transport Basics

A transport is the mechanism used for mods to communicate between a client instance and the server instance of the mod running.

There are two types of transports, ServerTransport and ClientTransport. A ServerTransports sends data from a client to the server, and a ClientTransport sends data from the server to a client.

Transports rely heavily on C# delegates to define what data is transfered.

Client Transports

Defining a Transport

The first step to creating a client transport is to define what data will be transfered. This is done using delegates:

public delegate void SendToClient(string option, int value);

In the delegate above named SendToClient we will be sending a string and integer value to a client. The name can be anything that makes sense and the delegate can have as many paramters as desired. (Note: There is a 1MB limit to sending data.) See below for a list of what types can be sent over transports.

The next step is to create a method that confirms to the delegate created. This method will be called on the client when it recieves a transport from the server.

[ClientOnly]
public void HandleClientTransportRecieved(string option, int value)
{
GetLogger().Info($"Recieved transport with values: {option} & {value}!");
}

The [ClientOnly] attribute is not strictly necessary, but it does help with code readability.

Registering a Transport

Then, the transport needs to be registered. A transport needs to be registered on both the client and the server no matter what type it is. This registration should happen when the mod is first enabled. Cubivox cannot process transports that are not properly registered on both sides.

Transporter.RegisterClientTransport<SendToClient>(ControllerKey.Create("TestMod", "SendToClient"), HandleClientTransportRecieved);

Transporter.RegisterClientTransport<>() is used to register a transport. The delegate type is put within the <> brackets.
Then the method takes a ControllerKey to identify the transport and a method that confirms to the delegate to be called when the transport is recieved on the client. The last method paramter is optional, excluding it will just register the transport for use. The RegisterClientTransport method can just be called a second time with the same controller key to add a handler method. (Multiple handler methods can also be added.)

Invoking a Transport

Finally, the server needs to invoke the transport to send data to the client. This is done with the Transporter.Transport<>() method.

Transporter.Transport<SendToClient>("Option 1", 25);

Full Example

public class TestMod : CubivoxMod
{
public TestMod(ModDescriptionFile modDescriptionFile, Logger logger) : base(modDescriptionFile, logger) { }

public delegate void SendToClient(string option, int value);

public override void OnEnable()
{
RegisterEvent<VoxelPlaceEvent>(HandleVoxelPlace);

Transporter.RegisterClientTransport<SendToClient>(ControllerKey.Create("TestMod", "SendToClient"), HandleClientTransportRecieved);
}

[ClientOnly]
public void HandleClientTransportRecieved(string option, int value)
{
GetLogger().Info($"Recieved transport with values {option} & {value} on the client!");
}

[ServerOnly]
public void HandleVoxelPlace(VoxelPlaceEvent evt)
{
Transporter.Transport<SendToClient>(evt.Player.GetName(), 22);
}
}