Limited Badge Stock Problem

Hello creators! I got problem.

How do I fix the scripts or GUI so that the number of remaining badges is updated online (in real time for all players)? My problem is that the GUI is not updated, that is, the remaining numbers (stock) do not change.

(If anything, I made a local script inside the GUI that shows (On textLabel) how many of how many (for example 50/50) Badges are left.)

And I also made a Server Side script (ServerScriptService), that:

  • The BadgeManager script uses the DataStore to keep track of how many players have received the badge.

  • It defines a method to fetch the current badge count and updates the count in the DataStore.

  • Every 5 seconds, it broadcasts the current badge count and remaining badges to all players using a RemoteEvent.

and local script:

  • The LocalScript listens for updates from the server via the RemoteEvent.

  • It updates the TextLabel based on the remaining badges. If the count reaches zero, it displays “Out Of Stock” in red.


Scripts:

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

-- Replace with your actual Badge ID
local badgeID = 123456789 -- example Badge ID
local maxBadgeCount = 10
local badgeDataStore = DataStoreService:GetDataStore("BadgeCounts")

-- Function to get the current badge count
local function getCurrentBadgeCount()
    local success, count = pcall(function()
        return badgeDataStore:GetAsync("BadgeCount") or 0
    end)

    return success and count or 0
end

-- Function to update the badge count in the data store
local function updateBadgeCount(count)
    pcall(function()
        badgeDataStore:SetAsync("BadgeCount", count)
    end)
end

-- Remote Event for GUI updates
local badgeCountUpdateEvent = Instance.new("RemoteEvent")
badgeCountUpdateEvent.Name = "BadgeCountUpdate"
badgeCountUpdateEvent.Parent = game.ReplicatedStorage

-- Function to check and update badge status
local function checkBadgeStatus(player)
    local currentCount = getCurrentBadgeCount()
    
    if currentCount < maxBadgeCount then
        -- Calculate remaining badges
        local remainingBadges = maxBadgeCount - currentCount
        -- Notify the client with the current remaining badge count
        badgeCountUpdateEvent:FireClient(player, remainingBadges)
    else
        -- Notify the client that badges are out of stock
        badgeCountUpdateEvent:FireClient(player, -1) -- Use -1 to indicate out of stock
    end
end

-- Player added event handler
Players.PlayerAdded:Connect(function(player)
    checkBadgeStatus(player)

    -- Optional: Update badge status for all existing players
    for _, existingPlayer in pairs(Players:GetPlayers()) do
        if existingPlayer ~= player then
            checkBadgeStatus(existingPlayer)
        end
    end
end)

-- Player removing event handler (if needed for cleanup)
Players.PlayerRemoving:Connect(function(player)
    -- Handle any cleanup if necessary
end)

LocalScript
local player = game.Players.LocalPlayer
local badgeCountLabel = script.Parent.Count -- Ensure this points to your TextLabel
local badgeCountUpdateEvent = game.ReplicatedStorage:WaitForChild("BadgeCountUpdate")

-- Function to update the badge count display
local function updateBadgeCountDisplay(count)
    if count == -1 then
        badgeCountLabel.Text = "Out Of Stock"
        badgeCountLabel.TextColor3 = Color3.fromRGB(255, 0, 0) -- Red color
    else
        badgeCountLabel.Text = "Remaining Badges: " .. tostring(count)
        badgeCountLabel.TextColor3 = Color3.fromRGB(255, 255, 255) -- Default color (white)
    end
end

-- Listen for badge count updates from the server
badgeCountUpdateEvent.OnClientEvent:Connect(updateBadgeCountDisplay)

-- Initial display when joining
updateBadgeCountDisplay(badgeCountUpdateEvent:InvokeServer())

2 Likes

per server or for all servers?
because if for every server so you need to use messageasync i don’t think datastore is suitable for this

2 Likes

For all servers. More precisely, so that each player on each server personally displays the remaining number of badges that can be obtained.

1 Like

you have any solutions? Me needed help really :sob:

1 Like

Use MessagingService and MemoryStore as @MythicalRealm_Studio said, DataStores are not good for this

2 Likes

okay, i rescripted, but it still not updates gui. Problem in the 16 line of the script:
Argument 3 missing or nil - Server - BadgeManager:16

Script:

local Players = game:GetService("Players")
local MemoryStoreService = game:GetService("MemoryStoreService")
local MessagingService = game:GetService("MessagingService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Constants
local BADGE_ID = 1559359473522609 -- Replace this with your actual Badge ID
local MAX_BADGE_COUNT = 3 -- Maximum number of badges available
local badgeStockKey = "BadgeCount1"

-- Initialize badge count in MemoryStore
local badgeStore = MemoryStoreService:GetSortedMap("BadgeStock")

-- Function to initialize badge count
local function initializeBadgeCount()
	badgeStore:SetAsync(badgeStockKey, MAX_BADGE_COUNT)
end

-- Function to get remaining badges
local function getRemainingBadges()
	local remainingBadges = badgeStore:GetAsync(badgeStockKey)
	return remainingBadges or MAX_BADGE_COUNT
end

-- Function to update badge count in MemoryStore and notify other servers
local function updateBadgeCount(count)
	badgeStore:SetAsync(badgeStockKey, count)
	MessagingService:PublishAsync("BadgeStockUpdate", count)
end

-- Remote Event for GUI updates
local badgeCountUpdateEvent = Instance.new("RemoteEvent")
badgeCountUpdateEvent.Name = "BadgeCountUpdate"
badgeCountUpdateEvent.Parent = ReplicatedStorage

-- Function to notify all players of the current badge status
local function notifyAllPlayers()
	local remainingBadges = getRemainingBadges()
	for _, player in pairs(Players:GetPlayers()) do
		badgeCountUpdateEvent:FireClient(player, remainingBadges)
	end
end

-- Listening for updates from other servers
MessagingService:SubscribeAsync("BadgeStockUpdate", function(message)
	local remainingBadges = message.Data
	notifyAllPlayers()
end)

-- Initialize badge count once when the server starts
initializeBadgeCount()

-- Periodically broadcast the badge count every 0.1 seconds
while true do
	notifyAllPlayers()
	wait(0.1) -- Update every 0.1 seconds
end

Local Script:

local player = game.Players.LocalPlayer
local badgeCountLabel = script.Parent -- Ensure this points correctly to your TextLabel
local badgeCountUpdateEvent = game.ReplicatedStorage:WaitForChild("BadgeCountUpdate")

-- Function to update the badge count display
local function updateBadgeCountDisplay(count)
	if count <= 0 then
		badgeCountLabel.Text = "Out of Stock"
		badgeCountLabel.TextColor3 = Color3.fromRGB(255, 0, 0) -- Red color for out of stock
	else
		badgeCountLabel.Text = tostring(count) .. "/" .. tostring(3) -- Display remaining / max badges
		badgeCountLabel.TextColor3 = Color3.fromRGB(0, 175, 0) -- Default color (white)
	end
end

-- Listen for badge count updates from the server
badgeCountUpdateEvent.OnClientEvent:Connect(updateBadgeCountDisplay)

-- Initialize display
updateBadgeCountDisplay(3) -- Starting value on GUI load

If you think what i stupid and dont understand simple things - im novice programmer

To add a new key or overwrite the value or sort key of a key in the sorted map, call MemoryStoreSortedMap:SetAsync() with the key name, its value, an expiration time in seconds and an optional sort key.

image

1 Like

Okay, now scripts works without errors, but it still cant count badge stock.

client :

local player = game.Players.LocalPlayer
local badgeCountLabel = script.Parent
local badgeCountUpdateEvent = game.ReplicatedStorage:WaitForChild("BadgeCountUpdate")

local function updateBadgeCountDisplay(count)
    if count <= 0 then
        badgeCountLabel.Text = "Out of Stock"
        badgeCountLabel.TextColor3 = Color3.fromRGB(255, 0, 0)
    else
        badgeCountLabel.Text = tostring(count) .. "/" .. tostring(3)
        badgeCountLabel.TextColor3 = Color3.fromRGB(0, 175, 0)
    end
end

badgeCountUpdateEvent.OnClientEvent:Connect(updateBadgeCountDisplay)

updateBadgeCountDisplay(3)

serverside

local Players = game:GetService("Players")
local MemoryStoreService = game:GetService("MemoryStoreService")
local MessagingService = game:GetService("MessagingService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local BADGE_ID = 1559359473522609
local MAX_BADGE_COUNT = 3
local badgeStockKey = "BadgeCount1"

local badgeStore = MemoryStoreService:GetSortedMap("BadgeStock")

local function initializeBadgeCount()
    local success, err = pcall(function()
        badgeStore:UpdateAsync(badgeStockKey, function(oldValue)
            return oldValue or MAX_BADGE_COUNT
        end, 86400)
    end)
    if not success then
        warn("Failed to initialize badge count:", err)
    end
end

local function getRemainingBadges()
    local success, result = pcall(function()
        return badgeStore:GetAsync(badgeStockKey)
    end)
    return success and result or MAX_BADGE_COUNT
end

local function updateBadgeCount(count)
    local success, err = pcall(function()
        badgeStore:UpdateAsync(badgeStockKey, function(oldValue)
            return count
        end, 86400)
    end)
    if success then
        MessagingService:PublishAsync("BadgeStockUpdate", count)
    else
        warn("Failed to update badge count:", err)
    end
end

local badgeCountUpdateEvent = Instance.new("RemoteEvent")
badgeCountUpdateEvent.Name = "BadgeCountUpdate"
badgeCountUpdateEvent.Parent = ReplicatedStorage

local function notifyAllPlayers()
    local remainingBadges = getRemainingBadges()
    for _, player in pairs(Players:GetPlayers()) do
        badgeCountUpdateEvent:FireClient(player, remainingBadges)
    end
end

local function awardBadge(player)
    local success, err = pcall(function()
        return badgeStore:UpdateAsync(badgeStockKey, function(oldValue)
            if oldValue and oldValue > 0 then
                return oldValue - 1
            end
            return oldValue
        end, 86400)
    end)
    
    if success then
        notifyAllPlayers()
    else
        warn("Failed to award badge:", err)
    end
end

MessagingService:SubscribeAsync("BadgeStockUpdate", function(message)
    notifyAllPlayers()
end)

initializeBadgeCount()

while true do
    notifyAllPlayers()
    wait(0.1)
end

you can use memorystore updateasync instead of setasync

1 Like

Not works. Maybe i must use not legacy run context for script? I just idk why it not works, output says nothing.

Also players get badges by this script:

script.Parent.Touched:Connect(function(part)
	if part.Parent:FindFirstChild("Humanoid") then
		local player = game.Players:GetPlayerFromCharacter(part.Parent)
		game:GetService("BadgeService"):AwardBadge(player.UserId, 1559359473522609) -- Put your badge id
	end
end)

--Note1: Create you badge now! it's free! you can create 5 badge for free now!
--Note2: if not work comment in this model 

                      --Script by Roblox Studio Indonesia--