Event Leaderboards

Read more about the Event Leaderboards system in Hiro here.

Initialize the event leaderboards system #

The event leaderboards system system relies on the Nakama System and an ILogger, both must be passed in as dependencies via the constructor.

1
2
var eventLeaderboardsSystem = new EventLeaderboardsSystem(logger, nakamaSystem);
systems.Add(eventLeaderboardsSystem);

Event leaderboard response #

The IEventLeaderboard response object includes the following properties:

PropertyTypeDescription
BestRanklongBest rank achieved across cohorts this phase.
CanClaimboolWhether the player can claim their reward.
CanRollboolWhether the player can roll into a new cohort right now.
CanRollWithClaimboolWhether the player can claim and roll in a single call.
CanUpdateboolWhether the player can submit scores to their current cohort.
IsActiveboolWhether the event leaderboard’s current phase is live.
MaxRollslongMaximum rolls allowed per phase.
RerollCountFreezeboolWhether the next roll is “free” (does not count against MaxRolls).
RollCooldownSeclongEffective cooldown between rolls, in seconds.
RollslongNumber of rolls the player has used this phase.
ScoreTargetlongTarget score for cohort completion.
ScoreTargetPlayerslongHow many players must reach the target.
TierintThe player’s current tier (0-indexed).
TierDeltaPerPhaselongTier adjustment applied when a phase expires.
ClaimTimeSeclongUnix timestamp when the player claimed their reward (0 if unclaimed).
EndTimeSeclongUnix timestamp when the player’s current cohort is scheduled to end.
ExpiryTimeSeclongUnix timestamp when the player’s phase pointer expires.
RollCooldownEndsSeclongWhen the current cooldown expires (UNIX timestamp).
ScoreTimeLimitEndsSeclongWhen this player’s time limit expires (UNIX timestamp).
ScoreTimeLimitSeclongPer-player time limit from roll time, in seconds.
StartTimeSeclongUnix timestamp when the player’s current cohort started.

Determine event leaderboard state #

When the server returns an Event Leaderboard, its current state is represented by a combination of boolean properties. Check if the player can claim rewards and roll into a new cohort simultaneously by reading the CanRollWithClaim property in the response.

IsActiveCanClaimCanRollDescription
FALSEFALSEFALSEVisible, but inactive. No actions are possible.
FALSETRUEFALSEVisible, but inactive. A reward from a previous phase can be claimed.
TRUEFALSEFALSEActive, a valid cohort exists and the player can submit scores (CanUpdate is true).
TRUEFALSETRUEActive, need to roll to get a cohort.
TRUETRUEFALSEActive, a completed cohort exists with an unclaimed reward. The player has no remaining rolls after claiming, or is waiting for a roll cooldown to expire.

Subscribe to changes in the event leaderboards system #

You can listen for changes in the event leaderboards system so that you can respond appropriately, such as updating the UI, by implementing the IObserver pattern, or use the SystemObserver<T> type which handles it for you.

1
2
3
4
5
var disposer = SystemObserver<EventLeaderboardsSystem>.Create(eventLeaderboardsSystem, system => {
    Instance.Logger.Info($"System updated.");

    // Update UI elements etc as necessary here...
});

List event leaderboards #

You can list all the available event leaderboards to the player by passing null as an argument.

1
var eventLeaderboards = await eventSystem.ListEventLeaderboardsAsync(null);

You can filter down the event leaderboards to only include those that belong to at least one of the given categories.

1
2
IEnumerable<string> categories = new List<string> { "level_completion", "race"};
var eventLeaderboards = await eventSystem.ListEventLeaderboardsAsync(categories);

By default, the response doesn’t include the scores of the event leaderboards. To have the response returning with the scores, set the boolean with_score on the request to true.

1
var eventLeaderboards = await eventSystem.ListEventLeaderboardsAsync(null, true);

Get an individual event leaderboard #

You can get an individual event leaderboard, including it’s records and information on it’s rewards.

1
var eventLeaderboard = await eventLeaderboardsSystem.GetEventLeaderboardAsync("<leaderboardId>");

Submit an event leaderboard score #

You can submit an event leaderboard score for the user. Check CanUpdate on the response to determine whether the player can still submit scores to their current cohort.

1
2
3
4
5
6
7
8
9
var score = 100;
var subscore = 10;
var eventLeaderboard = await eventLeaderboardsSystem.UpdateEventLeaderboardAsync("<leaderboardId>", score, subscore);

// Check if further score submissions are allowed
if (!eventLeaderboard.CanUpdate)
{
    // The player can no longer submit scores to this cohort
}

Claim rewards #

You can claim event leaderboard rewards for the user.

1
var eventLeaderboard = await eventLeaderboardsSystem.ClaimEventLeaderboardAsync("<leaderboardId>");

Roll into a cohort #

You can roll (or re-roll) the user into a cohort for a specific event leaderboard. The first roll in a phase places the player into a cohort for the first time. Subsequent rolls within the same phase are re-rolls, where the player leaves a completed cohort and joins a new one with fresh opponents.

1
2
// Roll into a cohort (first roll or re-roll after claiming separately)
var eventLeaderboard = await eventLeaderboardsSystem.RollEventLeaderboardAsync("<leaderboardId>");

To claim the current reward and roll into a new cohort in a single call, pass claimReward: true. This is the recommended approach for re-rolling as it avoids an extra round-trip.

1
2
// Claim reward and roll into a new cohort in one call
var eventLeaderboard = await eventLeaderboardsSystem.RollEventLeaderboardAsync("<leaderboardId>", claimReward: true);

Multi-roll game loop #

For score-based events where players can compete in multiple cohorts within a single phase, the typical flow looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 1. Roll into the first cohort
var el = await eventLeaderboardsSystem.RollEventLeaderboardAsync("score_rush");

// 2. Submit scores while the cohort is active
while (el.CanUpdate)
{
    el = await eventLeaderboardsSystem.UpdateEventLeaderboardAsync("score_rush", playerScore);
}

// 3. Check if can the player can roll into a cohort and claim rewards
if (el.CanRollWithClaim || el.CanRoll)
{
   // Claim and roll in one call
    el = await eventLeaderboardsSystem.RollEventLeaderboardAsync("score_rush", claimReward: el.CanRollWithClaim);
}
else if (el.CanClaim)
{
    // Just claim, done for this phase (or waiting for cooldown)
    el = await eventLeaderboardsSystem.ClaimEventLeaderboardAsync("score_rush");
}

Debug an event leaderboard #

You can fill an event leaderboard with dummy users and assign random scores to them for testing purposes.

This is intended for debugging use only.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var leaderboardId = "<leaderboardId>";
var targetCount = 50; // Optional target cohort size to fill to, otherwise fill to the max cohort size.

var minScore = 1;
var maxScore = 100;
var @operator = ApiOperator.SET;
var subscoreMin = 1;
var subscoreMax = 100;

// Fills cohort with debug players
await eventLeaderboardsSystem.DebugFillAsync(leaderboardId, targetCount);

// Sets randomly generated scores between a range for other players (does not change the user's score)
await eventLeaderboardsSystem.DebugRandomScoresAsync(leaderboardId, minScore, maxScore, @operator, subscoreMin, subscoreMax);