View as Markdown

Streaks

Read more about the Streaks system in Hiro here .

Functions #

List #

List all streaks and their current state and progress for a given user.

1
2
3
4
5
6
userId := "userId"

streaks, err := systems.GetStreaksSystem().List(ctx, logger, nk, userId)
if err != nil {
  return err
}

Update #

Update one or more streaks with the indicated counts for the given user.

1
2
3
4
5
6
7
userId := "userId"
streakIds := map[string]int64{"streakId_001": 5, "streakId_002": 2}

streaks, err := systems.GetStreaksSystem().Update(ctx, logger, nk, userId, streakIds)
if err != nil {
  return err
}

Claim #

Claim rewards for one or more streaks for the given user.

1
2
3
4
5
6
7
userId := "userId"
streakIds := []string{"streakId_001", "streakId_002"}

streaks, err := systems.GetStreaksSystem().Claim(ctx, logger, nk, userId, streakIds)
if err != nil {
  return err
}

Reset #

Reset progress on selected streaks for the given user. This also clears the streak’s stashed snapshot, so there is nothing left to restore: a streak cannot be reverted across a reset.

1
2
3
4
5
6
7
userId := "userId"
streakIds := []string{"streakId_001", "streakId_002"}

streaks, err := systems.GetStreaksSystem().Reset(ctx, logger, nk, userId, streakIds)
if err != nil {
  return err
}

Programmatic state control #

The Set, SetState, and Revert functions give studios programmatic control over streak state, so you can build your own flows on top of Hiro: paid revives and streak repair, VIP top-ups and streak-boost rewards, and customer-support restores. Pair them with the SetOnStreakChange hook to keep your own record of streak history. See the use cases below for a summary of which function fits each flow.

Set #

Set overwrites streak counts directly for the given user. Use it for count-level adjustments such as VIP top-ups, granted revives, or a customer-support count fix. Use grantRewards to control how rewards up to the new count are treated:

  • false marks every reward up to the new count as already claimed, so nothing becomes claimable. Use this to restore a player to a known state without re-granting rewards they have already received, such as a customer-support restore.
  • true leaves those rewards claimable, so the player can collect them. Use this for granted revives, VIP top-ups, or bonuses.

Counts are clamped to each streak’s max_count, and max_count_reached is never lowered by a Set.

1
2
3
4
5
6
7
8
userId := "userId"
counts := map[string]int64{"streakId_001": 5, "streakId_002": 2}
grantRewards := false

streaks, err := systems.GetStreaksSystem().Set(ctx, logger, nk, userId, counts, grantRewards)
if err != nil {
  return err
}

SetState #

Overwrite one or more streaks with the given snapshots for the given user. Use it when you need to write a streak’s full state rather than only its count, such as performing a precise customer-support restore. The snapshot is applied verbatim. Counts are clamped to max_count, and the streak’s update time is set to now so it isn’t immediately treated as lapsed. Pair it with the SetOnStreakChange hook to keep your own record of streak history.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
userId := "userId"
snapshots := map[string]*hiro.StreakSnapshot{
  "streakId_001": {
    Count:      5,
    ClaimCount: 3,
  },
}

streaks, err := systems.GetStreaksSystem().SetState(ctx, logger, nk, userId, snapshots)
if err != nil {
  return err
}

Set is a convenience wrapper over SetState. Use Set when you only need to change the count, and SetState when you need to write the full state, such as claim count, timestamps, and exactly which rewards were claimed. Both stash a revertible snapshot you can undo with Revert .

Revert #

Restore one or more streaks to their most recently stashed snapshot for the given user, swapping each streak with its current state. This is the simplest way to build paid revives or streak repair, undoing a loss from inactivity, or to roll back a bad Set or SetState batch. Because the swap is self-inverse, calling Revert again returns the streak to where it was.

A snapshot is stashed whenever you call Set or SetState , and automatically the first time a streak loses count to inactivity. That automatic snapshot captures the streak’s value from just before the decline began, and it is taken only once for a given stretch of inactivity, so it always holds the true pre-loss peak rather than a partly-decayed value.

Revert returns the streaks it restored, each back at that stashed snapshot. Streak IDs with no stashed snapshot are left unchanged and are not included in the returned result.

1
2
3
4
5
6
7
userId := "userId"
streakIds := []string{"streakId_001", "streakId_002"}

streaks, err := systems.GetStreaksSystem().Revert(ctx, logger, nk, userId, streakIds)
if err != nil {
  return err
}

For example, a player’s streak peaks at 9, then they go idle and it decays to 5. Hiro captures the pre-loss value of 9 once, when the decline is locked in, so a later Revert restores the full 9 rather than the decayed 5, even if the streak was read several times while the player was away.

Reset clears a streak’s stashed snapshot, so you cannot revert a streak across a reset.

Use cases #

Use caseFunctionNotes
Paid reviveRevert, or Set with grantRewards=falseRestores the pre-loss state in one call. Use Set if no snapshot remains, for example when the loss happened across a reset.
Streak repairRevertUndo a loss or gap from inactivity by restoring the stashed pre-loss state.
VIP top-up or streak-boost rewardSet with grantRewards=trueJump a player’s count ahead by one or more steps and leave the newly unlocked rewards claimable, for example as a reward or perk.
Customer-support restoreSetState, Revert, or Set with grantRewards=falseFull snapshot, stashed snapshot, or a count-only restore without re-granting rewards.

Hooks #

SetOnClaimReward #

Set a custom reward function which will run after a streak’s reward is rolled.

1
2
3
4
5
6
systems.GetStreaksSystem().SetOnClaimReward(OnClaimReward)

func OnClaimReward(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, userID, sourceID string, source *hiro.StreaksConfigStreak, rewardConfig *hiro.EconomyConfigReward, reward *hiro.Reward) (*hiro.Reward, error) {
	// Modify reward or take additional actions.
	return reward, nil
}

SetOnStreakChange #

Set a custom function which will run after streaks are persisted, with the streaks changed by the operation.

1
2
3
4
5
systems.GetStreaksSystem().SetOnStreakChange(OnStreakChange)

func OnStreakChange(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, userID string, changes []*StreakChange) {
	// Take additional actions.
}

Each change carries the streak’s state before and after the operation. Hiro only keeps the single most recent snapshot automatically, which is the one Revert restores. To keep a longer history, record these changes yourself in this hook. With your own log you can restore a streak to any earlier point, not just its most recent stashed state.

Types #

Streak Snapshot #

A point-in-time copy of a streak’s stored state, used by SetState and Revert .

PropertyTypeDescription
countint64The overall progress count.
count_current_resetint64The progress count submitted during the reset interval.
max_count_reachedint64The highest count the streak had reached.
claim_countint64The last count that was claimed.
create_time_secint64When the streak was first registered for this user, as a UNIX timestamp.
update_time_secint64When the streak was last updated, as a UNIX timestamp.
claim_time_secint64When the streak was last claimed, as a UNIX timestamp.
claimed_rewardsStreakRewardThe rewards that had already been claimed.

Streak Change #

Reports a streak’s state before and after a change. Passed to the SetOnStreakChange hook.

PropertyTypeDescription
idstringThe identifier of the streak that changed.
oldStreakSnapshotThe streak’s state before the change. nil if the streak did not exist beforehand.
newStreakSnapshotThe streak’s state after the change.