Ep 62. Large number Leaderboards

During this episode we created the global leaderboard system for our Simulator. Unfortunately, it turns out that Roblox’s data store system has a limit for how large of a number it can store, which is around 9.223 quintillion. Any numbers above this will get turned into a negative number, which is not what we want to happen. This limit is not exclusive to Roblox and is actually a limitation due to 64-bit computing, which is commonly used in the tech industry.

Luckily, we can easily solve this issue without doing much worth. It just requires using a little bit of math, which I actually discovered from this developer forum post.

Solution

We need to update a few functions and create one inside of the ServerScriptService/Leaderboards module script.

ServerScriptService/Leaderboards.lua
local function FetchLeaderboardStates()
	LeaderboardState = {
		Clicks = {},
		Rebirths = {},
		Gems = {}
	}
	
	CleanContainer()
	
	for leaderboardType, dataStore in DataStores do
		local pages = dataStore:GetSortedAsync(false, 100)
		local items = pages:GetCurrentPage()
		for index, item in items do
			local userId = item.key
			local storedValue = item.value
			local convertedValue = if storedValue == 0 then 0 else 1.0000001 ^ storedValue
			table.insert(LeaderboardState[leaderboardType], {
				UserId = userId,
				Amount = convertedValue
			})
			AddPlayerToLeaderboards(userId, leaderboardType, convertedValue, index)
		end
	end
	
	LastStateUpdateTime = os.time()
end

local function GetPlayerAmount(player: Player, currency: string)
	local currencyTable = LeaderboardState[currency]
	for index, info in currencyTable do
		if info.UserId == tostring(player.UserId) then
			return info.Amount
		end
	end
	
	return 1
end

local function SavePlayerData(player: Player)
	local earnings = Leaderboards.Earnings[player.UserId]
	if not earnings then return end
	
	for currency, earnedAmount in earnings do
		local hasEarned = earnedAmount > 0
		if hasEarned then
			local currentAmount = GetPlayerAmount(player, currency)
			local newAmount = currentAmount + earnedAmount 
			local convertedAmount = if newAmount == 0 then 0 else math.floor(math.log(newAmount) / math.log(1.0000001))
			DataStores[currency]:SetAsync(tostring(player.UserId), convertedAmount)
			Leaderboards.Earnings[player.UserId][currency] = 0
		end
	end
end
Contents