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.
Authenticate
Enable RTT
Create Lobby
Connect To Relay
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)