Issue: Title says it all. I want the SE event to fire only when players get badge. Any help is appreciated!
local function awardBadge(player,badgeId,Text)
local success1, badgeInfo = pcall(function()
return BS:GetBadgeInfoAsync(badgeId)
end)
if success1 then
if badgeInfo.IsEnabled then
local awarded, errorMessage = pcall(function()
BS:AwardBadge(player.UserId, badgeId)
end)
if not awarded then
warn("Error while awarding badge:", errorMessage)
else
if Text then
SE:FireAllClients(Text)
end
end
end
else
warn("Error while fetching badge info!")
end
end
This is my code and it gives too many requests which result in server lagging. Just realized I am using hasbadgeasync. What difference does it make?
local function awardBadge(player,badgeId,Text)
local hasBadge
local success, err = pcall(function()
hasBadge = BS:UserHasBadgeAsync(player.UserId, badgeId)
end)
if not success then
warn("Error while checking if player has badge:",err)
return
end
if hasBadge then
return
end
local success1, badgeInfo = pcall(function()
return BS:GetBadgeInfoAsync(badgeId)
end)
if success1 then
if badgeInfo.IsEnabled then
local awarded, errorMessage = pcall(function()
BS:AwardBadge(player.UserId, badgeId)
end)
if not awarded then
warn("Error while awarding badge:", errorMessage)
else
if Text then
SE:FireAllClients(Text)
end
end
end
else
warn("Error while fetching badge info!")
end
end
You can try storing the people who owns badges in a cache array, so you can either check if the player is registered in the cache or the player has the pass using the roblox function.
Don’t save the table in a datastore, it will just cause more troubles, also remove players from the cache table when they leave and lastly, UserHasBadgeAsync yields, that’s why you’re probably having apparent lag issues.
EDIT: The cache may not be needed if you manage to yield at the right moment.
Sorry, I was in a rush. Looks like the difference between the two is that UserHasBadge is depreciated… Sorry.
You had it right by using UserHasBadgeAsync.
You might be able to wrap the function a spawn function to remove the yeild aspect. Of course, this won’t decrease processing power needed to complete the task, so if the lag isn’t coming from the fact that it is a yeild, the spawn function won’t do a whole lot.
If the lag is coming from the processing power required, the cache will come in handy.
Here is my best estimate at what will help you:
local BS = game:GetService("BadgeService")
local PlayerHasPassCache = {}
local function awardBadge(player,badgeId,Text)
spawn(function()
local hasBadge
if PlayerHasPassCache[player.UserId] then -- // If the cache says that the player has the badge
hasBadge = PlayerHasPassCache[player.UserId]
else -- // If we don't have data on the player, or the player doesn't have the badge and we know that
local success, err = pcall(function()
hasBadge = BS:UserHasBadgeAsync(player.UserId, badgeId)
end)
if not success then
warn("Error while checking if player has badge:",err)
return
end
PlayerHasPassCache[player.UserId] = hasBadge -- // Add the player to the cache, even if they don't have the badge
end
if hasBadge then
return
end
local success1, badgeInfo = pcall(function()
return BS:GetBadgeInfoAsync(badgeId)
end)
if success1 then
if badgeInfo.IsEnabled then
local awarded, errorMessage = pcall(function()
BS:AwardBadge(player.UserId, badgeId)
end)
if not awarded then
warn("Error while awarding badge:", errorMessage)
else
if Text then
SE:FireAllClients(Text)
end
end
end
else
warn("Error while fetching badge info!")
end
end)
end
I’m curious as to why @jcnruad900 mentioned that you should remove the data from the array when the player leaves. Wouldn’t that just make us have to call the function if the player rejoined to the same server?
I think that if you keep the data in the array and the player has the pass, it’ll save you some processing power later on if that player rejoins. Please correct me if I am wrong.
Let’s say a player rejoins the same server, if they’re already registered in the cache with the non-ownership of the badge and in the meanwhile the player got the badge the script would not work for him even if he has got the badge.
Ah, I think I understand. My code would have worked in that case because I continued to use UserHasBadgeAsync if the value in the cached value false, but not if the cached value was true. I had not thought to add the false value in and use that per server instead of relying on UserHasBadgeAsync more than once.
Now, with a better understanding, here is the optimal code you are looking for @lagnis7859
local SE = game:GetService("ReplicatedStorage").RemoteEvent -- // Your remote event
local BS = game:GetService("BadgeService") -- // BadgeService
local PS = game:GetService("Players")
local PlayerHasPassCache = {} -- // Cache
local function awardBadge(player,badgeId,Text)
spawn(function()
local hasBadge
if PlayerHasPassCache[player.UserId] ~= nil then -- // If we have previously used UserHasBadgeAsync for this player in this server, we take that value
hasBadge = PlayerHasPassCache[player.UserId]
else -- // Only if we don't have data on the player
local success, err = pcall(function()
hasBadge = BS:UserHasBadgeAsync(player.UserId, badgeId)
end)
if not success then
warn("Error while checking if player has badge:",err)
return
end
PlayerHasPassCache[player.UserId] = hasBadge -- // Add the player to the cache, even if they don't have the badge
end
if hasBadge then
return
end
--[[ I was reading this over, and it looks like this is all just for another check if the player has the badge?
We already do that above, so we don't need this. Please correct me if I am wrong]]
--local success1, badgeInfo = pcall(function()
-- return BS:GetBadgeInfoAsync(badgeId)
--end)
--if success1 then
-- if badgeInfo.IsEnabled then
-- local awarded, errorMessage = pcall(function()
-- BS:AwardBadge(player.UserId, badgeId)
-- end)
-- if not awarded then
-- warn("Error while awarding badge:", errorMessage)
-- else
-- if Text then
-- SE:FireAllClients(Text)
-- end
-- end
-- end
--else
-- warn("Error while fetching badge info!")
--end
local awarded, errorMessage = pcall(function()
BS:AwardBadge(player.UserId, badgeId)
end)
if not awarded then
warn("Error while awarding badge:", errorMessage)
elseif Text then
SE:FireAllClients(Text)
end
end)
end
PS.PlayerRemoving:Connect(function(player)
-- // Sets the value to nil so if the player joins another server and earns the badge, they can still function properly in this server
PlayerHasPassCache[player.UserId] = nil
end)