BadgeUtil - efficient and optimized badge operations

BadgeUtil

Simple module for badge operations with cache and error handling.

:floppy_disk: Source Code | :package: Wally

https://create.roblox.com/store/asset/135419476607725/BadgeUtil

API Functions
  • awardBadgeLoop

    • BadgeUtil.awardBadgeLoop(player, badgeId, badgeName)
    • Checks if the Player doesn’t own the badge already, then repeatedly awards the badge until success.
    • Automatically updates the badge checking cache upon badge award.
  • BadgeInfo.getBadgeInfo

    • BadgeUtil.BadgeInfo.getBadgeInfo(badgeId)
    • Retrieves information about a badge.
    • Returns a table containing badge info; nil if failed.
  • CachedBadgeCheck.checkUserHasBadges

    • BadgeUtil.CachedBadgeCheck.checkUserHasBadges(userId, badgeIds)
    • Checks if the Player owns multiple badges.
    • Returns a dictionary mapping badge ids to whether the Player owns the badge. nil if the badge check fails.
  • CachedBadgeCheck.checkUserHasSingleBadge

    • BadgeUtil.CachedBadgeCheck.checkUserHasSingleBadge(userId, badgeId)
    • Checks if the Player owns the given badge.
    • Returns true if the Player owns the badge; false if the Player doesn’t own the badge; nil if the badge check fails.
  • CachedBadgeCheck.setUserHasBadge

    • BadgeUtil.CachedBadgeCheck.setUserHasBadge(userId, badgeId, hasBadge)
    • Updates and caches a known badge result for a Player and a badge.

About module

BadgeUtil is a module that makes badge awarding and checking more efficient and optimized!

The function awardBadgeLoop is a useful function that repeatedly awards a badge to a player until it’s successful.

  • It checks that the badge can be awarded and that the player doesn’t own the badge already.
  • The function requires the name of the badge.
    • This is to help developers ensure that the correct badge is being awarded, at the cost of having to republish the game to change a badge name.
  • While playtesting in Roblox Studio, instead of awarding a badge, a “mock” award message is printed.
  • Badge award is throttled at 1 badge award every 2 seconds for each player, so it takes 2 seconds to award two badges to any number of players, 4 seconds for three badges, and so on.

Badge checks (checkUserHasBadges) are done using both CheckUserBadgesAsync and UserHasBadgeAsync from Roblox’s BadgeService. Under Roblox’s rate limit, this maximizes the number of badges that can be checked!

  • Each result is cached for ~1 minute, meaning that you won’t reach the rate limit by repeatedly checking for the same badges on the same player.
  • It’s more efficient to call checkUserHasBadges on one giant list of badge ids than to call it on multiple smaller lists of badge ids.

Badge info retrieving (getBadgeInfo) functions essentially like BadgeService:GetBadgeInfoAsync, and it is provided as a submodule for convenience.

Additional info

While not directly related, here are some badge modules made by other people (for reference):

  • dig1t’s Badge module (badge service + cache)
  • Quenty’s BadgeUtils module (badge service + promise)

Some common practices to consider:

  • Don’t call the functions too quickly. You might want to add some debounce or rate limiter.
    • This will be handled internally by the module in the future.
      (currently, doing this can lead to multiple BadgeService calls before result is cached)
  • When working with the module from the client, calling badge awarding functions (e.g. awardBadgeLoop()) will do nothing and generate a warning.
    • Instead, create a remote callback to a server script that does server-sided checks and calls awardBadgeLoop().

Thank you for reading.
The module will be continuously updated to resolve any issues found and to implement additional features. Feel free to provide feedback or report problems!

8 Likes