Setting up an Event Service

Setup & Start

Step 1: Getting the Platform Data

Before starting the PusherEventService we first need to request information from the platform related to its notification settings. For the Pusher service, this will be the cluster our service needs to connect to, the key it needs to connect to, as well as any other options the platform has specified.
To get the platform information we use the GetPlatform request that is shared between and usable by both the ProjectClient and the PlayerClient, allowing us to use either one for this step. When creating the request we need to specify that we want our response with the platform's notification settings. This can be done so with a chaining method as shown in the example below:
Java
C# | Unity
C++
Unreal
import com.enjin.sdk.schemas.shared.queries.GetPlatform;
GetPlatform req = new GetPlatform()
.withNotificationDrivers();
using Enjin.SDK.Shared;
GetPlatform req = new GetPlatform()
.WithNotificationDrivers();
#include "enjinsdk/shared/GetPlatform.hpp"
using namespace enjin::sdk::shared;
GetPlatform req = GetPlatform()
.set_with_notifications();
#include "Shared/GetPlatform.h"
using namespace Enjin::Sdk::Shared;
FGetPlatform Req = FGetPlatform()
.SetWithNotifications();
Now that we have created the request we can send it to the platform. We will need to use the method with the matching name as our request and the result we are expecting is a GraphQL response wrapping the Platform model, which represents the type of the same name in the platform's API.
Java
C# | Unity
C++
Unreal
import com.enjin.sdk.graphql.GraphQLResponse;
import com.enjin.sdk.models.Platform;
// Using an authenticated client
GraphQLResponse<Platform> res = client.getPlatform(req).get();
Platform platform = res.getData();
using Enjin.SDK.Graphql;
using Enjin.SDK.Models;
// Using an authenticated client
GraphqlResponse<Platform> res = client.GetPlatform(req).Result;
Platform platform = res.Result;
#include "enjinsdk/GraphqlResponse.hpp"
#include "enjinsdk/models/Platform.hpp"
using namespace enjin::sdk::graphql;
using namespace enjin::sdk::models;
// Using an authenticated client
GraphqlResponse<Platform> res = client->get_platform(req).get();
Platform platform = res.get_result().value();
#include "GraphQlResponse.h"
#include "Model/Platform.h"
using namespace Enjin::Sdk::GraphQl;
using namespace Enjin::Sdk::Model;
// Using an authenticated client
Client->GetPlatform()
.Next([](TGraphQlResponseForOnePtr<FPlatform> Res)
{
FPlatform Platform = Res->GetResult().GetValue();
});

Step 2: Starting the Service

To start the Pusher event service we must use its builder class construct it and pass the Platform model instance from the previous step into its constructor.
Java
C# | Unity
C++
Unreal
import com.enjin.sdk.events.PusherEventService;
PusherEventService service = PusherEventService
.builder()
.platform(platform)
.build();
using Enjin.SDK.Events;
PusherEventService service = PusherEventService
.Builder()
.Platform(platform)
.Build();
#include "enjinsdk/PusherEventService.hpp"
#include <memory>
using namespace enjin::sdk::events;
std::unique_ptr<PusherEventService> service = PusherEventService::builder()
.platform(platform)
.build();
#include "PusherEventService.h"
using namespace Enjin::Sdk::Event;
TUniquePtr<FPusherEventService> Service = FPusherEventService::Builder()
.Platform(Platform)
.Build();
Now that we have instantiated our event service we may call its start method. Starting the service tends to involve asynchronous processes. For this reason, event services in the SDKs return an asynchronous type, which we may use to wait for the process to complete if we choose to do so.
Java
C# | Unity
C++
Unreal
import java.util.concurrent.Future;
Future<Void> future = service.start();
using System.Threading.Tasks;
Task task = service.Start();
#include <future>
std::future<void> future = service->start();
Service->Start().Next([](bool bResult)
{
// Handle service start
});
Additionally the event service comes with a method which we may use at any time to check if the event service is connected to the server as shown below:
Java
C# | Unity
C++
Unreal
boolean result = service.isConnected();
bool result = service.IsConnected();
bool result = service->is_connected();
bool bResult = Service->IsConnected();

Step 3: Shutting Down the Service

Once we are done using the event service we may want to shut it down to free up any resources that may have been acquired during its lifetime. To do so we call the service's shutdown method, and as with the start method, we may use the asynchronous type returned to wait for this process to finish.
Java
C# | Unity
C++
Unreal
import java.util.concurrent.Future;
Future<Void> future = service.shutdown();
future.get();
using System.Threading.Tasks;
Task task = service.Shutdown();
task.Wait();
#include <future>
std::future<void> future = service->shutdown();
future.wait();
Service->Shutdown().Next([](bool bResult)
{
// Handle service shut down
});
In the C++ and Unreal SDKs the destructor for the Pusher event service will close the WebSocket connection if it has not already been closed.

Service Notifications

The event services offer ways for us to listen for and handle when certain flags are raised within them, such as when they establish a connection with the server, are disconnected from the server, or encounter an error. However, the API for doing so varies between the SDKs, so we will look at them individually throughout this section.

Java SDK

For the Java SDK we provide the IConnectionEventListener interface which may be passed to the service through any of the start() methods which accept it as an argument. The example code block below shows how this listener may be set with an anonymous class.
import com.enjin.sdk.events.IConnectionEventListener;
service.start(new IConnectionEventListener() {
@Override
public void onConnect() { /* Place code here */ }
@Override
public void onDisconnect() { /* Place code here */ }
@Override
public void onError(Exception e) { /* Place code here */ }
});
The IConnectionEventListener interface utilizes default methods, which enables us to override only the methods we wish to implement ourselves and ignore the rest.

C# and Unity SDKs

For the C# and Unity SDKs we utilize .NET's field like events for raising events related to the service's internal state. The example code block below shows how these events may be used with a delegate.
service.Connected += (sender, args) => { /* Place code here */ };
service.Disconnected += (sender, args) => { /* Place code here */ };
service.Error += (sender, exception) => { /* Place code here */ };

C++ SDK

For the C++ SDK we utilize the function wrapper std::function from the standard library as our handler for notifications raised by the service. The example code block below shows how these handlers may be used with lambda expressions.
service->set_connected_handler([]() { /* Place code here */ });
service->set_disconnected_handler([]() { /* Place code here */ });
service->set_error_handler([](const std::exception& e) { /* Place code here */ });

Unreal SDK

For the Unreal SDK we utilize Unreal's architecture for declaring, binding, and executing events. The example code block below shows how we may bind to these events.
Service->OnConnected().AddLambda([]() { /* Place code here */ });
Service->OnDisconnected().AddLambda([]() { /* Place code here */ });
Service->OnError().AddLambda([](const FString& Error) { /* Place code here */ });
Documentation for this architecture is available at Unreal Engine's documentation site: