Skip to main content

Manage backfill tickets using AGS OSS

Last updated on February 27, 2024
note

Armada is not available on AGS Starter tier yet. It's coming soon!

Overview

This guide covers the basics of managing backfill ticket using AGS OSS. The AccelByte OnlineSubsystem (OSS) is used to interact with V2 sessions and matchmaking backfill.

Goals

  • Fetch session information from a dedicated server.
  • Accept or reject backfill proposals from a dedicated server.
  • Enable or disable backfill from a dedicated server.

Prerequisites

  • You are familiar with our Lobby, Session and Matchmaking services.

  • You have knowledge of Unreal Engine, including use of the OnlineSubsystem (OSS).

  • You have access to the Admin Portal and the Namespace for your game.

  • You have configured a session template with type set to DS, and set the appropriate deployment.

  • You have configured a match pool and match ruleset, and associated them with the session template.

  • Your game client has been integrated with AGS Matchmaking.

  • You have V2 sessions enabled in your DefaultEngine.ini:

    [OnlineSubsystemAccelByte]
    bEnableV2Sessions=true
  • Game servers must have the followings permissions:

    PermissionsActionUsage
    NAMESPACE:{namespace}:MATCHMAKING:BACKFILLCREATE, READ, UPDATE, DELETETo manage backfill ticket

Backfill Proposal Flow

In this section, you will get an understanding of the backfill proposal flow, that is executed between the Matchmaking service and a dedicated server.

After a game session has been created and invites sent to the matched players, the Session service will request a dedicated server be provisioned through the DS Hub.

Once a dedicated server is ready, the connection information will be returned to the game session, and it will attempt to connect.

  1. After the game session is successfully connected to the dedicated server, the server can query the session data.

  2. If the game session is not full, it can match with additional players, if either auto-backfill has been enabled or by submitting a backfill ticket directly to the Matchmaking service.

  3. If a backfill request has been submitted, either automatically or manually, the Matchmaking service will return proposals to the dedicated server.

  4. The dedicated server will then process the proposal, and evaluate if it is viable. It is important to check if there is still room in the game session before accepting the proposal, as another player may have already taken the open spot due to a race condition.

  5. The dedicated server then accepts or rejects the proposal, informing the Matchmaking service. If accepted, the new player will receive an invite to join the game session.

Fetch Session Information

Once a game session is connected to a dedicated server, players will be able to use the connection details stored in the session. This will enable them to connect with the dedicated server. At the same time, the server can query information about the sessions and connected players.

  1. To begin with, you need to register our game server with Armada, by retrieving the V2 session interface:

    FOnlineSessionV2AccelBytePtr SessionInterface;
    if (!ensure(FOnlineSessionV2AccelByte::GetFromWorld(GetWorld(), SessionInterface)))
    {
    return;
    }
  2. Listen for an event which marks session assignment to the server, OnServerReceivedSession:

    const FOnServerReceivedSessionDelegate OnServerReceivedSessionDelegate =
    FOnServerReceivedSessionDelegate::CreateUObject(
    this, &MyClass::OnServerReceivedSession);
    FDelegateHandle OnServerReceivedSessionDelegateHandle =
    SessionInterface->AddOnServerReceivedSessionDelegate_Handle(
    OnServerReceivedSessionDelegate);
  3. Invoke the RegisterServer method:

    const FOnRegisterServerComplete OnRegisterServerCompleteDelegate =
    FOnRegisterServerComplete::CreateUObject(
    this, &MyClass::OnRegisterServerComplete);
    SessionInterface->RegisterServer(SessionName, OnRegisterServerCompleteDelegate);
  4. Inside the delegate handler for OnServerReceivedSession, you can fetch the session the same way as a game client would. First, retrieve the session interface again, then the session:

    // Here `SessionName` is a param to the session received delegate
    FNamedOnlineSession* Session = SessionInterface->GetNamedSession(SessionName);
    if (!ensure(Session != nullptr))
    {
    return;
    }
  5. The server can now interact with the session settings and data.

  6. It's generally good practice to clear the OnServerReceivedSession delegate, using the FDelegateHandle used earlier.

Enable and Disable Backfill

Match backfill can be enabled in one of two ways. The first is as a configuration setting from within a match ruleset if it's applicable for your game mode. Or you can create and submit a backfill ticket directly from the dedicated server.

To enable backfill, retrieve the session interface, then create a backfill ticket:

const FOnCreateBackfillTicketComplete OnCreateBackfillTicketCompleteDelegate =
FOnCreateBackfillTicketComplete::CreateUObject(
this, &MyClass::OnCreateBackfillTicketComplete);
SessionInterface->CreateBackfillTicket(
NAME_GameSession, OnCreateBackfillTicketComplete);
note

You can also supply a match pool name to this methodif you want a particular match pool other than the original.

To disable backfill, delete the backfill ticket:

const FOnDeleteBackfillTicketComplete OnDeleteBackfillTicketCompleteDelegate =
FOnDeleteBackfillTicketComplete::CreateUObject(
this, &MyClass::OnDeleteBackfillTicketComplete);
SessionInterface->DeleteBackfillTicket(
NAME_GameSession, OnDeleteBackfillTicketCompleteDelegate);

Handle backfill proposals

tip

We recommend that the dedicated server periodically checks if the session is not at full capacity. This allows the server to recreate backfill tickets, as the team member of the session may be out of sync with the backfill ticket. By doing so, the existing game session has an opportunity to reach full capacity through the matchmaking process.

If session backfill has been requested, either by having auto-backfill configured in the match ruleset, or requested directly from the server, the server will begin to receive proposals if the game session has open spots for more players.

Matchmaking backfill proposals are sent to the dedicated server, where they can be accepted or rejected. Before registering the server, add a delegate handler for receiving backfill proposals:

FOnBackfillProposalReceivedDelegate OnBackfillProposalReceivedDelegate =
FOnBackfillProposalReceivedDelegate::CreateUObject(
this, &MyClass::OnBackfillProposalReceived);
FDelegateHandle OnBackfillProposalReceivedDelegateHandle =
SessionInterface->AddOnBackfillProposalReceivedDelegate_Handle(
OnBackfillProposalReceivedDelegate);

Inside that handler, you can decide whether to accept or reject the proposal. First, retrieve the session interface. Then, after some decision logic, accept or reject the proposal. To accept:

FOnAcceptBackfillProposalComplete OnAcceptBackfillProposalCompleteDelegate =
FOnAcceptBackfillProposalComplete::CreateUObject(
this, &MyClass::OnAcceptBackfillProposalComplete);
SessionInterface->AcceptBackfillProposal(
NAME_GameSession, Proposal, false, OnAcceptBackfillProposalCompleteDelegate)

Or reject:

FOnRejectBackfillProposalComplete OnRejectBackfillProposalCompleteDelegate = 
FOnRejectBackfillProposalComplete::CreateUObject(
this, &MyClass::OnRejectBackfillProposalComplete);
SessionInterface->RejectBackfillProposal(
NAME_GameSession, Proposal, false, OnRejectBackfillProposalCompleteDelegate);
note

The third argument to both of these accept and reject methods is a boolean that tells the session interface whether you want to stop backfilling. In the examples, you will still receive backfill proposals after rejecting or accepting, due to the false argument passed to the respective methods.

Example: Get a Backfill Ticket ID

When the auto_backfill match ruleset setting is enabled, and the matchmaking process produces a non-full game, a backfill ticket will be generated before the session is created. The resulting effect is that when a DS receives its session, if desired, the DS can check for the presence of a backfill ticket ID to indicate whether the incoming match will have automatic backfill:

const FNamedOnlineSession* Session =
SessionInterface->GetNamedSession(NAME_GameSession);
if (!ensure(Session != nullptr))
{
return;
}

const TSharedPtr<FOnlineSessionInfoAccelByteV2> SessionInfo =
StaticCastSharedPtr<FOnlineSessionInfoAccelByteV2>(Session->SessionInfo);
if (!ensure(SessionInfo.IsValid()))
{
return;
}

const TSharedPtr<FAccelByteModelsV2GameSession> SessionData =
SessionInfo->GetBackendSessionDataAsGameSession();
if (!ensure(SessionData.IsValid()))
{
return;
}

const bool bIsBackfillEnabled = !SessionData->BackfillTicketID.IsEmpty();

Troubleshooting

In this section, you can find common errors and issues that may occur when using the service, along with recommendations on how to resolve them.

Session Update Fails due to a Version Conflict

Currently, a DS will not automatically receive session updates, so it's possible that the server can run into issues trying to update a session. When the session data on the DS side becomes stale, updating the session can result in a version conflict error. While it's possible to detect this kind of error from the error message logged when invoking UpdateSession, you can also make use of an error delegate for this specific case:

FOnSessionUpdateConflictErrorDelegate OnSessionUpdateConflictErrorDelegate =
FOnSessionUpdateConflictErrorDelegate::CreateUObject(
this, &MyClass::OnSessionUpdateConflictError);
SessionInterface->AddOnSessionUpdateConflictErrorDelegate_Handle(
OnSessionUpdateConflictErrorDelegate);

Because there is no real generic solution for the session service, or AccelByte OSS, to decide which session settings to update in the case of a conflict, the above delegate can be used to retry the update and/or to house logic for resolving conflicts.

note

When an update fails, the session data will automatically be refreshed from the backend, and the conflict error delegate will receive a copy of the session settings passed to the failed update.