All Collections
Multiplayer
Basic Relay Service Example in C#
Basic Relay Service Example in C#

Most basic Relay Service examples done in C#.

Jason Liang avatar
Written by Jason Liang
Updated over a week ago

Although brainCloud has several Relay Service examples, they are big projects that can be hard to follow. This example is meant to be lean, with best practices.

Flow

This is the flow of the app. Each step will wait for the previous step to be successfully before proceeding.

  1. Authenticate

  2. Enable RTT

  3. Create Lobby

  4. Connect To Relay

  5. Send message to me "Hello World!"

Portal Setup

A few settings need to be set properly in the portal. In our example, we are going to have only 1 player join the lobby in "ready" state. Then start the match immediately.

Enable RTT in Core App Info / Advanced Settings:

Create a new server in Cloud Code / My Servers. Copy the settings bellow so the server starts as soon as we have 1 ready player in the lobby.

Configure at least 1 region in the Regions tab:

Create a new lobby in Multiplayer / Lobbies:

And copy the following rules so the game starts right away when the first ready player joins:

Project

In Visual Studio, create a new C# Console Application. Grab latest brainCloud client library here: https://github.com/getbraincloud/braincloud-csharp
And add the project BrainCloudClient to your solution.

Project Source

Here is the complete source for the example Program.cs.

using BrainCloud;
using BrainCloud.JsonFx.Json;
using System;
using System.Text;
using System.Threading;
using System.Collections.Generic;

namespace RelayExampleApp
{
    class Program
    {
        static BrainCloudWrapper bc;
        static bool isRunning = true;
        static RelayConnectOptions connectOptions =
            new RelayConnectOptions();
        // Change this to try different connection type
        static RelayConnectionType connectionType = RelayConnectionType.UDP;

        static void Main(string[] args)
        {
            bc = new BrainCloudWrapper("RelayExampleApp");
            bc.Init("https://sharedprod.braincloudservers.com/dispatcherv2",
                    "your app secret", "your app id", "1.0");
            bc.Client.EnableLogging(true);
            bc.AuthenticateAnonymous(onAuthenticated, onFailed);

            // Main event loop running at 60fps as a game would.
            while (isRunning)
            {
                bc.Update();
                Thread.Sleep(16);
            }
        }

        static void onFailed(int status, int reasonCode,
                             string jsonError, object cbObject)
        {
            Console.WriteLine("Error: " + jsonError);
            isRunning = false;
        }

        static void onAuthenticated(string jsonResponse, object cbObject)
        {
            bc.RTTService.RegisterRTTLobbyCallback(onLobbyEvent);
            bc.RTTService.EnableRTT(RTTConnectionType.WEBSOCKET,
                                    onRTTEnabled, onFailed);
        }

        static void onRTTEnabled(string jsonResponse, object cbObject)
        {
            var algo = new Dictionary<string, object>();
            algo["strategy"] = "ranged-absolute";
            algo["alignment"] = "center";
            List<int> ranges = new List<int>();
            ranges.Add(1000);
            algo["ranges"] = ranges;
            bc.LobbyService.FindOrCreateLobby(
                "READY_START", 0, 1, algo,
                new Dictionary<string, object>(), 0, true,
                new Dictionary<string, object>(), "all",
                new Dictionary<string, object>(), null, null, onFailed);
        }

        static void onLobbyEvent(string json)
        {
            var response =
                JsonReader.Deserialize<Dictionary<string, object>>(json);
            var data = response["data"] as Dictionary<string, object>;

            switch (response["operation"] as string)
            {
                case "DISBANDED":
                    var reason = data["reason"]
                        as Dictionary<string, object>;
                    var reasonCode = (int)reason["code"];
                    if (reasonCode == ReasonCodes.RTT_ROOM_READY)
                        connectToRelay();
                    else
                        onFailed(0, 0, "DISBANDED != RTT_ROOM_READY", null);
                    break;

                // ROOM_READY contains information on how to connect to the
                // relay server.
                case "ROOM_READY":
                    var connectData = data["connectData"]
                        as Dictionary<string, object>;
                    var ports = connectData["ports"]
                        as Dictionary<string, object>;

                    connectOptions.ssl = false;
                    connectOptions.host = connectData["address"] as string;

                    if (connectionType == RelayConnectionType.WEBSOCKET)
                        connectOptions.port = (int)ports["ws"];
                    else if (connectionType == RelayConnectionType.TCP)
                        connectOptions.port = (int)ports["tcp"];
                    else if (connectionType == RelayConnectionType.UDP)
                        connectOptions.port = (int)ports["udp"];

                    connectOptions.passcode = data["passcode"] as string;
                    connectOptions.lobbyId = data["lobbyId"] as string;
                    break;
            }
        }

        static void connectToRelay()
        {
            bc.RelayService.RegisterSystemCallback(systemCallback);
            bc.RelayService.RegisterRelayCallback(relayCallback);
            bc.RelayService.Connect(connectionType, connectOptions,
                                    onRelayConnected, onFailed);
        }

        static void onRelayConnected(string jsonResponse, object cbObject)
        {
            Console.WriteLine("On Relay Connected");

            short myNetId = bc.RelayService.GetNetIdForProfileId(
                bc.Client.AuthenticationService.ProfileId);
            byte[] bytes = Encoding.ASCII.GetBytes("Hello World!");
            bc.RelayService.Send(bytes, myNetId, true, true,
                                 BrainCloudRelay.CHANNEL_HIGH_PRIORITY_1);
        }

        static void systemCallback(string json)
        {
            Console.WriteLine("systemCallback: " + json);
        }

        static void relayCallback(byte[] data)
        {
            string message = Encoding.ASCII.GetString(data, 0, data.Length);
            Console.WriteLine("relayCallback: " + message);
        }
    }
}

Output

If everything is working as expected, you should see this in your log: (After removing all the noise)

Did this answer your question?