BadgeService3 | Set up badges for free in your project!

Here’s an tutorial for anyone using DataStore2. I will also be making a dedicated tutorial on how to use it with Profile Service. There are some extra tips inside this video as well.

2 Likes

Not gonna switch from old version because profile service/DS2 is too confusing to me. Old badgeService3 has force save which I can use for my autosave script and it is more friendly to me.

Idk, if this would work but would it be possible to use them across places, if you got a badge in one place? Could you script it to give you a tool in another?

Here’s an example of how this module can be used with the Nevermore Engine:

local Nevermore = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local PlayerDataStoreManager = Nevermore("PlayerDataStoreManager")
local badgeService3 = Nevermore(game.ReplicatedStorage.BadgeService3)

local dataStoreManager = PlayerDataStoreManager.new(DataStoreService:GetDataStore("PlayerData"), function(player) return tostring(player.UserId) end)

function loadBadges(player, store)
	return store:Load("Badges", {}):Then(function(data)
		return badgeService3:LoadProfile(player, data)
	end):Catch(function(...)
		warn("Failed to load", ...)
	end)
end

function handlePlayerAdded(player)
	local dataStore = dataStoreManager:GetDataStore(player)
	local badgeStore = dataStore:GetSubStore("BadgeStore")
	
	loadBadges(player, badgeStore):Then(function(profile)
		delay(5, function()
			if profile.Data then
				profile:AwardBadge("Welcome")
			end
		end)

		profile:onUpdate(function()
			badgeStore:Store(profile.Data)
		end)		
	end):Catch(function()
		player:Kick()
	end)
end

Players.PlayerAdded:Connect(handlePlayerAdded)
for _, player in pairs(Players:GetPlayers()) do
	handlePlayerAdded(player)
end
1 Like

You don’t actually need to use any of these two services, you can make your own data saving solution, in this case even integrate it into your old BadgeService3 solution, how ever it is a big more tricky to do so with BadgeService3 v1, it isn’t that hard but it is a bit harder. I can make a v1 handler for you if you like, it shouldn’t be that hard to convert your scripts into.

Also thanks for letting me know you used BadgeService3 v1.

Also I don’t know what you mean by force save? :thinking:

The old version has :SavePlayerData(plr) function or something like that, not sure but theres a function to save player data manually

Speaking of which I think that you should keep the old version as well (and the old documentation) because its more easier and simple to use. The old one is just better for me because it does the saving and loading automatically. Or make the v2 more simple to use

The biggest problem for me is that it’s too complex to use for “crappy” develolers like me.

You’re not crappy… You’re a beginner, when I made that I was probably about your skill.

I moved away from BadgeService3 v1 because of a bunch of problems and this, eventually does the same except it doesn’t save, to learn it is easier, it’s just harder to set up. Anyways you can message me if you want a handler for it. I can make it act just like BadgeService3.

3 Likes

Looks clever. Quick question:

Is this badge just a notification, or one that appears on there profile / Inventory?

Thank you.

It uses datastores, so no. It doesn’t show up on your profile.


3 Likes

BadgeService3 has been updated to 2.0.0.

This release is more so a bug fix, and optimization and memory leak fix. If you use it, please update it.

The Signal API here was updated / replaced, so it fixes some issues from the past.
You shoudn’t have any problems migrating to this new version, simply get your ‘Badges’ sub-module, delete the rest, and replace the old stuff with the new code and you should be fine.

You can now use :Connect() on the Signals, like: badgeProfile.onBadgeAwarded:Connect(), and also you can still use badgeProfile:onBadgeAwarded().

You can download it from here:

https://www.roblox.com/library/6525256722/BadgeService3

3 Likes

BadgeService3 v2 was updated to 3.0.0

Updating is recommended.

There were some updates on which no one was particularly notified of, there were no releases as they were minor updates.

This reply will show significant changes in the module, other things are simple code changes which improve things, but don’t change behaviour.

The updates that I will mention below are changes which can break your current installation of BadgeService3, which might require you to re-write certain parts of your scripts.

If you specifically messed with .Data then, please read below.


This update is a complete re-write, and with it, there are some behaviour changes, these can break your scripts if you messed with .Data specifically.

Should I worry?

If you did one of these, you should look into re-writing some code if needed.

  • If you used .Data to check for if someone owns a badge or anything.
  • If you awarded badges through .Data;
  • If you mutated .Data at all;
  • If you saved .Data together with a bunch of other data. In the sense of literally mixing everything, if you had a ‘partition’ like PlayerData.Badges, you’re safe from this.

What changed with .Data?

.Data is NOT a dictionary anymore. Before it was a dictionary with this base in mind:

{
    [badgeId] = true;
}

Now it’s an array, like this:

{
    badgeId1,
    badgeId2
}

Why was this changed?

I should not have done it with a dictionary anyways, I did it with dictionaries instead for the first time because that would mean that there’s no duplicates, which isn’t an issue unless you handled it poorly.

One thing this helps with, is converting from older data from the v1, since it follows the same format.

Data in datastores are saved in a JSON string, and using arrays is WAY less costly,
It can save up to about 6 characters for each badge owned!

Example:

Old - Dictionary

["WelcomeBadge": true, "10Kills": true, "20Kills": true]

New - Array

["WelcomeBadge", "10Kills", "20Kills"]

Does past data get automatically converted?

The answer to that is yes! BadgeService3 will automatically convert the data if needed.

Data can only get converted when you call any of these functions:

  • :AwardBadge
  • :RemoveBadge
  • :OwnsBadge
  • :GetOwnedBadges

This conversion is only done once, and only if needed.

The table reference to .Data is changed to the converted data, and .OnUpdate is fired.

I haven’t done any of that, what do I need / should change?

Not much, most of the changes are actually syntax changes.
With that said, events are now PastalCase. You can still use camelCase, but the right way now is .OnUpdate, and not .onUpdate.

Here’s the most noted changes:

  • .Data is now an array.

  • :WaitForProfile doesn’t use Heartbeat anymore, instead it will check whenever a new badge profile is loaded, and check if it’s the player you’re checking.

  • :GetOwnedBadges is now faster.

There really aren’t many, it’s mostly a optimization and code organization update, but it helps the future of the module.

3 Likes

Update 3.0.0 > 3.2.0


  • Updated Signal Class
  • Fixed issue where having a string url instead of a number assetId in Badge.Image would not allow notifications to use that Badge’s Image.

Now, I also made all settings full-on PascalCase, therefore if you messed with any settings, please change it so that your code is using PascalCase on them.

3 Likes

The problem with this is that does it actually display the badge on the user’s profile?

No it does not. It is just a replacement for people without funding and also engages the player more.

3 Likes

Would be very useful for people who wish to experiment with badges before actually creating badges.

May be useful to me in the future but I’m not sure.

Cool system! :+1:

If a player gets a badge using this, can I transfer that badge to another game for a reward. Is there some sort of ID?

If you’re saving data in a custom database, then you can do that between games. If you’re using Roblox datastores you can do that between places.

I suggest you look deeper into how this module works, you should get some better explaining.

BS3 doesn’t handle datastoring, you need to hook it up to whatever you’re saving data with.
Roblox datastores can get and set data inside the same game and secondary places, however it can’t share data with other Roblox games.

If you’re using HttpService and setting up a database yourself, then yes that would mean that data could be shared between games.

No idea what any of that means, haha, but thanks, I’ll look into it.

Basically, if they earn a badge, they can earn a reward in another game, not the one they got the badge in.

You’ll have to set up a database (perhaps Firebase) for storing whether they own each badge.

1 Like