How do I optimize this function to make it faster?

I need to get a list of many roblox games. Everything is fine but the issue is that it takes A LONGGG TIME if the list is huge.

function populateInventory()
	local slots = script.Parent.InventoryFrame.Slots
	local games = parseString(game.Players.LocalPlayer.dataStats.CollectedGames.Value)
	local template = script.Template

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[item.Name] = true
		end
	end

	for key, value in ipairs(games) do
		local decodedJSON = MarketPlaceService:GetProductInfo(value)
		local gameName = decodedJSON["Name"]
		local gameId = decodedJSON["AssetId"]

		if not existingItems[gameId] then
			local points = 0
			local decodedDate = date(decodedJSON["Created"])
			if decodedJSON["Creator"]["HasVerifiedBadge"] == true then
				points += 10
			end
			local placevisits = game.ReplicatedStorage.GetPlaceVisits:InvokeServer(gameId)
			task.wait(0)
			if placevisits then
				if placevisits > 9999 then
					points += 25 
				end
			else
				warn("not working :/")
			end
			if tonumber(decodedDate.year) < 2010 then
				points += 15
			elseif tonumber(decodedDate.year) < 2014 then 
				points += 10
			end
			if decodedJSON["IconImageAssetId"] ~= 0 then
				points += 5
			end
			if string.find(decodedJSON["Name"], "Content Deleted", 1, true) then
				points += 1
			end
			if decodedJSON["AssetId"] == 17044556893 then
				-- HOW DID THEY ROLL THIS. THEY NEED 1 BILLION FOLLOWERS
				points += 500
			end
			local rank
			
			if points <= 5 then
				rank = "Common"
			elseif points <= 10 then
				rank = "Uncommon"
			elseif points <= 25 then
				rank = "Rare"
			elseif points <= 35 then
				rank = "Epic"
			elseif points <= 45 then
				rank = "Mythic"
			end
			
			local myGame = template:Clone()
			myGame.PlaceName.Text = gameName
			if decodedJSON["IconImageAssetId"] == 0 then
				myGame.PlaceIcon.Image = "rbxassetid://17055597657"
			else
				myGame.PlaceIcon.Image = "rbxassetid://" .. decodedJSON["IconImageAssetId"]
			end
			myGame.PlaceCreator.Text = decodedJSON["Creator"].Name
			myGame.Parent = slots
			myGame.Name = gameId
			myGame.BackgroundColor3 = rarityColors[rank]
			myGame.PlaceId.Value = gameId
		end
	end
end
4 Likes

Simple answer: you dont

Better answer: make a loading system, dont load them all at once, load them as they’re needed. Requests/pages, load 100 at a time, if they need to load more, load another 100, and so on

3 Likes

Cache the productInfo. It’s going to be the same speed the first time you run the code but it will be faster on later calls.

Code:

local infoCache = {}

local function populateInventory()
	local slots = script.Parent.InventoryFrame.Slots
	local games = parseString(game.Players.LocalPlayer.dataStats.CollectedGames.Value)
	local template = script.Template

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[item.Name] = true
		end
	end

	for key, value in ipairs(games) do
		local decodedJSON = infoCache[value] or MarketPlaceService:GetProductInfo(value)
		
		if not infoCache[value] then
			infoCache[value] = decodedJSON
		end
		
		local gameName = decodedJSON["Name"]
		local gameId = decodedJSON["AssetId"]

		if not existingItems[gameId] then
			local points = 0
			local decodedDate = date(decodedJSON["Created"])
			
			if decodedJSON["Creator"]["HasVerifiedBadge"] == true then
				points += 10
			end
			
			local placevisits = game.ReplicatedStorage.GetPlaceVisits:InvokeServer(gameId)
			
			if placevisits then
				if placevisits > 9999 then
					points += 25 
				end
			else
				warn("not working :/")
			end
			
			if tonumber(decodedDate.year) < 2010 then
				points += 15
			elseif tonumber(decodedDate.year) < 2014 then 
				points += 10
			end
			
			if decodedJSON["IconImageAssetId"] ~= 0 then
				points += 5
			end
			
			if string.find(decodedJSON["Name"], "Content Deleted", 1, true) then
				points += 1
			end
			
			if decodedJSON["AssetId"] == 17044556893 then
				-- HOW DID THEY ROLL THIS. THEY NEED 1 BILLION FOLLOWERS
				points += 500
			end
			
			local rank

			if points <= 5 then
				rank = "Common"
			elseif points <= 10 then
				rank = "Uncommon"
			elseif points <= 25 then
				rank = "Rare"
			elseif points <= 35 then
				rank = "Epic"
			elseif points <= 45 then
				rank = "Mythic"
			end

			local myGame = template:Clone()
			myGame.Name = gameId
			myGame.PlaceName.Text = gameName
			myGame.PlaceCreator.Text = decodedJSON["Creator"].Name
			myGame.PlaceIcon.Image = decodedJSON["IconImageAssetId"] == 0 and "rbxassetid://17055597657" or "rbxassetid://" .. decodedJSON["IconImageAssetId"]
			myGame.BackgroundColor3 = rarityColors[rank]
			myGame.PlaceId.Value = gameId
			myGame.Parent = slots
		end
	end
end

I just tried this script.
It is the same speed each time, it is not faster.

Send your entire code, I feel like you declared infoCache in the wrong place.

local TweenService = game:GetService("TweenService")
local MarketPlaceService = game:GetService("MarketplaceService")
local diceSides = {
	11105170518, -- 1
	11105171156, -- 2
	11105171911, -- 3
	11105172844, -- 4
	11105173494, -- 5
	11105173941 -- 6
}

local infoCache = {}

local rarityColors = {
	["Common"] = Color3.fromRGB(68, 68, 68),
	["Uncommon"] = Color3.fromRGB(102, 100, 94),
	["Rare"] = Color3.fromRGB(70, 182, 70),
	["Epic"] = Color3.fromRGB(48, 97, 234),
	["Legendary"] = Color3.fromRGB(255, 243, 79),
	["Mythic"] = Color3.fromRGB(142, 56, 229)
}
local pickedSide

local canRoll = true

game.ReplicatedStorage.RollPlace:FireServer()

function date(str)
	local data = {}
	local y,m,d,h,i,s,t=str:match"(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).(%d+)Z"
	data.year=y data.month=m data.day=d data.hour=h data.min=i data.sec=s data.milli=t
	data.sinceEpoch=os.time(data)
	return data
end

function parseString(inputString)
	local dictionary = {}
	for number in inputString:gmatch("[^,]+") do
		table.insert(dictionary, tonumber(number))
	end
	return dictionary
end

function getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	if decodedjson["Creator"]["HasVerifiedBadge"] == true then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Creator is verified."
		game.ReplicatedStorage.GimmehBadge:FireServer(1443573582565408)
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if placevisits > 9999 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +25 Points. Has more than 10k visits."
		placeFrame.Specials.TotalPointsV.Value += 25
		game.ReplicatedStorage.GimmehBadge:FireServer(2689485152267094)
	end	

	if tonumber(decodedDate.year) < 2010 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +15 Points. Made before 2010"
		placeFrame.Specials.TotalPointsV.Value += 15
		game.ReplicatedStorage.GimmehBadge:FireServer(1391843739894243)
	elseif tonumber(decodedDate.year) < 2014 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Made before 2014"
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if decodedjson["IconImageAssetId"] ~= 0 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +5 Points. Has a custom icon."
		placeFrame.Specials.TotalPointsV.Value += 5
	end
	if string.find(decodedjson["Name"], "Content Deleted", 1, true) then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +1 Point. Is content deleted."
		placeFrame.Specials.TotalPointsV.Value += 1
		game.ReplicatedStorage.GimmehBadge:FireServer(1107810746136549)
	end 
	if decodedjson["AssetId"] == 17044556893 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +500 Points. You rolled game rng!! HOW?"
		placeFrame.Specials.TotalPointsV.Value += 500
		game.ReplicatedStorage.GimmehBadge:FireServer(581872078322536)
	end

	local rank

	if placeFrame.Specials.TotalPointsV.Value <= 5 then
		rank = "Common"
	elseif placeFrame.Specials.TotalPointsV.Value <= 10 then
		rank = "Uncommon"
	elseif placeFrame.Specials.TotalPointsV.Value <= 25 then
		rank = "Rare"
	elseif placeFrame.Specials.TotalPointsV.Value <= 35 then
		rank = "Epic"
	elseif placeFrame.Specials.TotalPointsV.Value <= 45 then
		rank = "Mythic"
		game.ReplicatedStorage.GlobalMessage:FireServer(rank)
	end
	local data = {
		rarity = rank,
		points = placeFrame.Specials.TotalPointsV.Value
	}
	return data
end

function setupPlace(decodedjson, placevisits)
	local placeFrame = script.Parent.PlaceUnlock
	if decodedjson["IconImageAssetId"] == 0 then
		placeFrame.PlaceIcon.Image = "rbxassetid://17055597657"
	else
		placeFrame.PlaceIcon.Image = "rbxassetid://" .. decodedjson["IconImageAssetId"]
		print("Icon Asset Id: " .. decodedjson["IconImageAssetId"])
		placeFrame.DefaultIconNotice.Visible = false
	end
	placeFrame.Specials.Special.Text = " "
	placeFrame.Specials.TotalPointsV.Value = 0
	placeFrame.CreatorName.Text = "Created by " .. decodedjson["Creator"].Name
	local decodedDate = date(decodedjson["Created"])
	placeFrame.CreationDate.Text =  "Created on " .. decodedDate.year .. "/" .. decodedDate.month .. "/" .. decodedDate.day
	placeFrame.PlaceName.Text = decodedjson["Name"]
	placeFrame.PlaceDescription.Text = decodedjson["Description"]
	placeFrame.PlaceVisits.Text = "Visits: " .. placevisits
	placeFrame.PlaceID.Text = "Place Id: " .. decodedjson["AssetId"]

	local rarity = getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	print(rarity)
	local rank = rarity.rarity
	local points = rarity.points
	placeFrame.Specials.TotalPoints.Text = "Total Points: " .. points .. "\nRanking: " .. rank
end

function roll()
	if canRoll == true then

		local decodedJSON = game.HttpService:JSONDecode(game.Players.LocalPlayer.dataStats.decodedPlaceJSON.Value)
		local visits = game.Players.LocalPlayer.dataStats.RecentRollVisits.Value
		setupPlace(decodedJSON, visits)
		script.Parent.RollButton.Text = "Rolling"
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice1.Image = "rbxassetid://" .. pickedSide
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice2.Image = "rbxassetid://" .. pickedSide
		game.ReplicatedStorage.RollPlace:FireServer() -- for next roll, so they dont have to wait as long
		canRoll = false
		if script.Parent.FastRollOn.Value == true then
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		else
			script.Parent.Dice1.BackgroundTransparency = 0
			script.Parent.Dice2.BackgroundTransparency = 0
			script.Parent.Dice1.ImageTransparency = 0
			script.Parent.Dice2.ImageTransparency = 0
			script.Parent.DiceRoll:Play()
			local dice1Tween1 = TweenService:Create(script.Parent.Dice1, TweenInfo.new(1), {Rotation = 360, Position = UDim2.new(0.584, 0,0.498, 0)})
			local dice2Tween1 = TweenService:Create(script.Parent.Dice2, TweenInfo.new(0.9), {Rotation = 450, Position = UDim2.new(0.681, 0,0.498, 0)})
			dice1Tween1:Play()
			dice2Tween1:Play()
			wait(0.8)
			script.Parent.Drumroll:Play()
			wait(1)
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		end
	end 
end

local function populateInventory()
	local slots = script.Parent.InventoryFrame.Slots
	local games = parseString(game.Players.LocalPlayer.dataStats.CollectedGames.Value)
	local template = script.Template

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[item.Name] = true
		end
	end

	for key, value in ipairs(games) do
		local decodedJSON = infoCache[value] or MarketPlaceService:GetProductInfo(value)

		if not infoCache[value] then
			infoCache[value] = decodedJSON
		end

		local gameName = decodedJSON["Name"]
		local gameId = decodedJSON["AssetId"]

		if not existingItems[gameId] then
			local points = 0
			local decodedDate = date(decodedJSON["Created"])

			if decodedJSON["Creator"]["HasVerifiedBadge"] == true then
				points += 10
			end

			local placevisits = game.ReplicatedStorage.GetPlaceVisits:InvokeServer(gameId)

			if placevisits then
				if placevisits > 9999 then
					points += 25 
				end
			else
				warn("not working :/")
			end

			if tonumber(decodedDate.year) < 2010 then
				points += 15
			elseif tonumber(decodedDate.year) < 2014 then 
				points += 10
			end

			if decodedJSON["IconImageAssetId"] ~= 0 then
				points += 5
			end

			if string.find(decodedJSON["Name"], "Content Deleted", 1, true) then
				points += 1
			end

			if decodedJSON["AssetId"] == 17044556893 then
				-- HOW DID THEY ROLL THIS. THEY NEED 1 BILLION FOLLOWERS
				points += 500
			end

			local rank

			if points <= 5 then
				rank = "Common"
			elseif points <= 10 then
				rank = "Uncommon"
			elseif points <= 25 then
				rank = "Rare"
			elseif points <= 35 then
				rank = "Epic"
			elseif points <= 45 then
				rank = "Mythic"
			end

			local myGame = template:Clone()
			myGame.Name = gameId
			myGame.PlaceName.Text = gameName
			myGame.PlaceCreator.Text = decodedJSON["Creator"].Name
			myGame.PlaceIcon.Image = decodedJSON["IconImageAssetId"] == 0 and "rbxassetid://17055597657" or "rbxassetid://" .. decodedJSON["IconImageAssetId"]
			myGame.BackgroundColor3 = rarityColors[rank]
			myGame.PlaceId.Value = gameId
			myGame.Parent = slots
		end
	end
end


script.Parent.RollButton.Activated:Connect(function()
	roll()
end)

script.Parent.InfoButton.Activated:Connect(function()
	script.Parent.Information.Visible = true
end)

script.Parent.Information.ExitButton.Activated:Connect(function()
	script.Parent.Information.Visible = false
end)

script.Parent.AutoRollButton.Activated:Connect(function()
	if script.Parent.AutoRollOn.Value == false then
		script.Parent.AutoRollOn.Value = true
		script.Parent.AutoRollButton.Text = "Auto Roll: On"
	else
		script.Parent.AutoRollOn.Value = false
		script.Parent.AutoRollButton.Text = "Auto Roll: Off"
	end
end)

script.Parent.InventoryButton.Activated:Connect(function()
	script.Parent.Loading.Visible = true
	populateInventory()
	script.Parent.Loading.Visible = false
	script.Parent.InventoryFrame.Visible = true

end)

script.Parent.InventoryFrame.ExitButton.Activated:Connect(function()
	script.Parent.InventoryFrame.Visible = false
end)

script.Parent.MoreLuckButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = true
end)

script.Parent.DevProducts.ExitButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = false
end)

script.Parent.FastRollButton.Activated:Connect(function()
	if MarketPlaceService:UserOwnsGamePassAsync(game.Players.LocalPlayer.UserId, 777801444) then
		if script.Parent.FastRollOn.Value == false then
			script.Parent.FastRollOn.Value = true
			script.Parent.FastRollButton.Text = "Fast Roll: On"
		else
			script.Parent.FastRollOn.Value = false
			script.Parent.FastRollButton.Text = "Fast Roll: Off"
		end
	else
		MarketPlaceService:PromptGamePassPurchase(game.Players.LocalPlayer, 777801444)
	end
end)
script.Parent.PurchaseAllFrontPageGames.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = true
end)

script.Parent.PopularGamesPack.ExitButton.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = false
end)
for _, item in pairs(script.Parent:GetDescendants()) do
	if item:IsA("TextButton") or item:IsA("ImageButton") then
		local soundScript = script.ButtonSound:Clone()
		soundScript.Parent = item
		soundScript.Enabled = true
	end
end

while wait(0.5) do
	if script.Parent.AutoRollOn.Value == true then
		roll()
	end
end

Try this and tell me what it prints:

local TweenService = game:GetService("TweenService")
local MarketPlaceService = game:GetService("MarketplaceService")
local diceSides = {
	11105170518, -- 1
	11105171156, -- 2
	11105171911, -- 3
	11105172844, -- 4
	11105173494, -- 5
	11105173941 -- 6
}

local infoCache = {}
local visitsCache = {}

local rarityColors = {
	["Common"] = Color3.fromRGB(68, 68, 68),
	["Uncommon"] = Color3.fromRGB(102, 100, 94),
	["Rare"] = Color3.fromRGB(70, 182, 70),
	["Epic"] = Color3.fromRGB(48, 97, 234),
	["Legendary"] = Color3.fromRGB(255, 243, 79),
	["Mythic"] = Color3.fromRGB(142, 56, 229)
}
local pickedSide

local canRoll = true

game.ReplicatedStorage.RollPlace:FireServer()

function date(str)
	local data = {}
	local y,m,d,h,i,s,t=str:match"(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).(%d+)Z"
	data.year=y data.month=m data.day=d data.hour=h data.min=i data.sec=s data.milli=t
	data.sinceEpoch=os.time(data)
	return data
end

function parseString(inputString)
	local dictionary = {}
	for number in inputString:gmatch("[^,]+") do
		table.insert(dictionary, tonumber(number))
	end
	return dictionary
end

function getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	if decodedjson["Creator"]["HasVerifiedBadge"] == true then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Creator is verified."
		game.ReplicatedStorage.GimmehBadge:FireServer(1443573582565408)
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if placevisits > 9999 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +25 Points. Has more than 10k visits."
		placeFrame.Specials.TotalPointsV.Value += 25
		game.ReplicatedStorage.GimmehBadge:FireServer(2689485152267094)
	end	

	if tonumber(decodedDate.year) < 2010 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +15 Points. Made before 2010"
		placeFrame.Specials.TotalPointsV.Value += 15
		game.ReplicatedStorage.GimmehBadge:FireServer(1391843739894243)
	elseif tonumber(decodedDate.year) < 2014 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Made before 2014"
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if decodedjson["IconImageAssetId"] ~= 0 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +5 Points. Has a custom icon."
		placeFrame.Specials.TotalPointsV.Value += 5
	end
	if string.find(decodedjson["Name"], "Content Deleted", 1, true) then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +1 Point. Is content deleted."
		placeFrame.Specials.TotalPointsV.Value += 1
		game.ReplicatedStorage.GimmehBadge:FireServer(1107810746136549)
	end 
	if decodedjson["AssetId"] == 17044556893 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +500 Points. You rolled game rng!! HOW?"
		placeFrame.Specials.TotalPointsV.Value += 500
		game.ReplicatedStorage.GimmehBadge:FireServer(581872078322536)
	end

	local rank

	if placeFrame.Specials.TotalPointsV.Value <= 5 then
		rank = "Common"
	elseif placeFrame.Specials.TotalPointsV.Value <= 10 then
		rank = "Uncommon"
	elseif placeFrame.Specials.TotalPointsV.Value <= 25 then
		rank = "Rare"
	elseif placeFrame.Specials.TotalPointsV.Value <= 35 then
		rank = "Epic"
	elseif placeFrame.Specials.TotalPointsV.Value <= 45 then
		rank = "Mythic"
		game.ReplicatedStorage.GlobalMessage:FireServer(rank)
	end
	local data = {
		rarity = rank,
		points = placeFrame.Specials.TotalPointsV.Value
	}
	return data
end

function setupPlace(decodedjson, placevisits)
	local placeFrame = script.Parent.PlaceUnlock
	if decodedjson["IconImageAssetId"] == 0 then
		placeFrame.PlaceIcon.Image = "rbxassetid://17055597657"
	else
		placeFrame.PlaceIcon.Image = "rbxassetid://" .. decodedjson["IconImageAssetId"]
		print("Icon Asset Id: " .. decodedjson["IconImageAssetId"])
		placeFrame.DefaultIconNotice.Visible = false
	end
	placeFrame.Specials.Special.Text = " "
	placeFrame.Specials.TotalPointsV.Value = 0
	placeFrame.CreatorName.Text = "Created by " .. decodedjson["Creator"].Name
	local decodedDate = date(decodedjson["Created"])
	placeFrame.CreationDate.Text =  "Created on " .. decodedDate.year .. "/" .. decodedDate.month .. "/" .. decodedDate.day
	placeFrame.PlaceName.Text = decodedjson["Name"]
	placeFrame.PlaceDescription.Text = decodedjson["Description"]
	placeFrame.PlaceVisits.Text = "Visits: " .. placevisits
	placeFrame.PlaceID.Text = "Place Id: " .. decodedjson["AssetId"]

	local rarity = getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	print(rarity)
	local rank = rarity.rarity
	local points = rarity.points
	placeFrame.Specials.TotalPoints.Text = "Total Points: " .. points .. "\nRanking: " .. rank
end

function roll()
	if canRoll == true then

		local decodedJSON = game.HttpService:JSONDecode(game.Players.LocalPlayer.dataStats.decodedPlaceJSON.Value)
		local visits = game.Players.LocalPlayer.dataStats.RecentRollVisits.Value
		setupPlace(decodedJSON, visits)
		script.Parent.RollButton.Text = "Rolling"
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice1.Image = "rbxassetid://" .. pickedSide
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice2.Image = "rbxassetid://" .. pickedSide
		game.ReplicatedStorage.RollPlace:FireServer() -- for next roll, so they dont have to wait as long
		canRoll = false
		if script.Parent.FastRollOn.Value == true then
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		else
			script.Parent.Dice1.BackgroundTransparency = 0
			script.Parent.Dice2.BackgroundTransparency = 0
			script.Parent.Dice1.ImageTransparency = 0
			script.Parent.Dice2.ImageTransparency = 0
			script.Parent.DiceRoll:Play()
			local dice1Tween1 = TweenService:Create(script.Parent.Dice1, TweenInfo.new(1), {Rotation = 360, Position = UDim2.new(0.584, 0,0.498, 0)})
			local dice2Tween1 = TweenService:Create(script.Parent.Dice2, TweenInfo.new(0.9), {Rotation = 450, Position = UDim2.new(0.681, 0,0.498, 0)})
			dice1Tween1:Play()
			dice2Tween1:Play()
			wait(0.8)
			script.Parent.Drumroll:Play()
			wait(1)
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		end
	end 
end

local function populateInventory()
	local start = os.clock()

	local slots = script.Parent.InventoryFrame.Slots
	local games = parseString(game.Players.LocalPlayer.dataStats.CollectedGames.Value)
	local template = script.Template

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[item.Name] = true
		end
	end
	
	print(`External Processing: {os.clock() - start}`)
	
	start = os.clock()
	
	for key, value in ipairs(games) do
		local decodedJSON = infoCache[value] or MarketPlaceService:GetProductInfo(value)

		if not infoCache[value] then
			infoCache[value] = decodedJSON
		end

		local gameName = decodedJSON["Name"]
		local gameId = decodedJSON["AssetId"]

		if not existingItems[gameId] then
			local points = 0
			local decodedDate = date(decodedJSON["Created"])

			if decodedJSON["Creator"]["HasVerifiedBadge"] == true then
				points += 10
			end

			local placevisits = visitsCache[gameId] or game.ReplicatedStorage.GetPlaceVisits:InvokeServer(gameId)

			if placevisits then
				if not visitsCache[gameId] then
					visitsCache[gameId] = placevisits
				end
				
				if placevisits > 9999 then
					points += 25 
				end
			else
				warn("not working :/")
			end

			if tonumber(decodedDate.year) < 2010 then
				points += 15
			elseif tonumber(decodedDate.year) < 2014 then 
				points += 10
			end

			if decodedJSON["IconImageAssetId"] ~= 0 then
				points += 5
			end

			if string.find(decodedJSON["Name"], "Content Deleted", 1, true) then
				points += 1
			end

			if decodedJSON["AssetId"] == 17044556893 then
				-- HOW DID THEY ROLL THIS. THEY NEED 1 BILLION FOLLOWERS
				points += 500
			end

			local rank

			if points <= 5 then
				rank = "Common"
			elseif points <= 10 then
				rank = "Uncommon"
			elseif points <= 25 then
				rank = "Rare"
			elseif points <= 35 then
				rank = "Epic"
			elseif points <= 45 then
				rank = "Mythic"
			end

			local myGame = template:Clone()
			myGame.Name = gameId
			myGame.PlaceName.Text = gameName
			myGame.PlaceCreator.Text = decodedJSON["Creator"].Name
			myGame.PlaceIcon.Image = decodedJSON["IconImageAssetId"] == 0 and "rbxassetid://17055597657" or "rbxassetid://" .. decodedJSON["IconImageAssetId"]
			myGame.BackgroundColor3 = rarityColors[rank]
			myGame.PlaceId.Value = gameId
			myGame.Parent = slots
		end
	end
	
	print(`Create UI: {os.clock() - start}`)
end


script.Parent.RollButton.Activated:Connect(roll)

script.Parent.InfoButton.Activated:Connect(function()
	script.Parent.Information.Visible = true
end)

script.Parent.Information.ExitButton.Activated:Connect(function()
	script.Parent.Information.Visible = false
end)

script.Parent.AutoRollButton.Activated:Connect(function()
	if script.Parent.AutoRollOn.Value == false then
		script.Parent.AutoRollOn.Value = true
		script.Parent.AutoRollButton.Text = "Auto Roll: On"
	else
		script.Parent.AutoRollOn.Value = false
		script.Parent.AutoRollButton.Text = "Auto Roll: Off"
	end
end)

script.Parent.InventoryButton.Activated:Connect(function()
	script.Parent.Loading.Visible = true
	populateInventory()
	script.Parent.Loading.Visible = false
	script.Parent.InventoryFrame.Visible = true

end)

script.Parent.InventoryFrame.ExitButton.Activated:Connect(function()
	script.Parent.InventoryFrame.Visible = false
end)

script.Parent.MoreLuckButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = true
end)

script.Parent.DevProducts.ExitButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = false
end)

script.Parent.FastRollButton.Activated:Connect(function()
	if MarketPlaceService:UserOwnsGamePassAsync(game.Players.LocalPlayer.UserId, 777801444) then
		if script.Parent.FastRollOn.Value == false then
			script.Parent.FastRollOn.Value = true
			script.Parent.FastRollButton.Text = "Fast Roll: On"
		else
			script.Parent.FastRollOn.Value = false
			script.Parent.FastRollButton.Text = "Fast Roll: Off"
		end
	else
		MarketPlaceService:PromptGamePassPurchase(game.Players.LocalPlayer, 777801444)
	end
end)
script.Parent.PurchaseAllFrontPageGames.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = true
end)

script.Parent.PopularGamesPack.ExitButton.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = false
end)
for _, item in pairs(script.Parent:GetDescendants()) do
	if item:IsA("TextButton") or item:IsA("ImageButton") then
		local soundScript = script.ButtonSound:Clone()
		soundScript.Parent = item
		soundScript.Enabled = true
	end
end

while wait(0.5) do
	if script.Parent.AutoRollOn.Value == true then
		roll()
	end
end

Also, I meant that it gets faster when you call the function for subsequent times.

External Processing: 0.00022960000205785036 - Client - ClientHandler:210

Create UI: 37.77866819998599 - Client - ClientHandler:290

Is this on your first or second time opening the inventory?

first

extracharactersbecauseyes

Could you open it another time and show me what it prints?

Ignore what I said, try this script:

local TweenService = game:GetService("TweenService")
local MarketPlaceService = game:GetService("MarketplaceService")
local diceSides = {
	11105170518, -- 1
	11105171156, -- 2
	11105171911, -- 3
	11105172844, -- 4
	11105173494, -- 5
	11105173941 -- 6
}

local currentTask = nil
local rarityColors = {
	["Common"] = Color3.fromRGB(68, 68, 68),
	["Uncommon"] = Color3.fromRGB(102, 100, 94),
	["Rare"] = Color3.fromRGB(70, 182, 70),
	["Epic"] = Color3.fromRGB(48, 97, 234),
	["Legendary"] = Color3.fromRGB(255, 243, 79),
	["Mythic"] = Color3.fromRGB(142, 56, 229)
}
local pickedSide

local canRoll = true

game.ReplicatedStorage.RollPlace:FireServer()

function date(str)
	local data = {}
	local y,m,d,h,i,s,t=str:match"(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).(%d+)Z"
	data.year=y data.month=m data.day=d data.hour=h data.min=i data.sec=s data.milli=t
	data.sinceEpoch=os.time(data)
	return data
end

function parseString(inputString)
	local dictionary = {}
	for number in inputString:gmatch("[^,]+") do
		table.insert(dictionary, tonumber(number))
	end
	return dictionary
end

function getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	if decodedjson["Creator"]["HasVerifiedBadge"] == true then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Creator is verified."
		game.ReplicatedStorage.GimmehBadge:FireServer(1443573582565408)
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if placevisits > 9999 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +25 Points. Has more than 10k visits."
		placeFrame.Specials.TotalPointsV.Value += 25
		game.ReplicatedStorage.GimmehBadge:FireServer(2689485152267094)
	end	

	if tonumber(decodedDate.year) < 2010 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +15 Points. Made before 2010"
		placeFrame.Specials.TotalPointsV.Value += 15
		game.ReplicatedStorage.GimmehBadge:FireServer(1391843739894243)
	elseif tonumber(decodedDate.year) < 2014 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Made before 2014"
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if decodedjson["IconImageAssetId"] ~= 0 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +5 Points. Has a custom icon."
		placeFrame.Specials.TotalPointsV.Value += 5
	end
	if string.find(decodedjson["Name"], "Content Deleted", 1, true) then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +1 Point. Is content deleted."
		placeFrame.Specials.TotalPointsV.Value += 1
		game.ReplicatedStorage.GimmehBadge:FireServer(1107810746136549)
	end 
	if decodedjson["AssetId"] == 17044556893 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +500 Points. You rolled game rng!! HOW?"
		placeFrame.Specials.TotalPointsV.Value += 500
		game.ReplicatedStorage.GimmehBadge:FireServer(581872078322536)
	end

	local rank

	if placeFrame.Specials.TotalPointsV.Value <= 5 then
		rank = "Common"
	elseif placeFrame.Specials.TotalPointsV.Value <= 10 then
		rank = "Uncommon"
	elseif placeFrame.Specials.TotalPointsV.Value <= 25 then
		rank = "Rare"
	elseif placeFrame.Specials.TotalPointsV.Value <= 35 then
		rank = "Epic"
	elseif placeFrame.Specials.TotalPointsV.Value <= 45 then
		rank = "Mythic"
		game.ReplicatedStorage.GlobalMessage:FireServer(rank)
	end
	local data = {
		rarity = rank,
		points = placeFrame.Specials.TotalPointsV.Value
	}
	return data
end

function setupPlace(decodedjson, placevisits)
	local placeFrame = script.Parent.PlaceUnlock
	if decodedjson["IconImageAssetId"] == 0 then
		placeFrame.PlaceIcon.Image = "rbxassetid://17055597657"
	else
		placeFrame.PlaceIcon.Image = "rbxassetid://" .. decodedjson["IconImageAssetId"]
		print("Icon Asset Id: " .. decodedjson["IconImageAssetId"])
		placeFrame.DefaultIconNotice.Visible = false
	end
	placeFrame.Specials.Special.Text = " "
	placeFrame.Specials.TotalPointsV.Value = 0
	placeFrame.CreatorName.Text = "Created by " .. decodedjson["Creator"].Name
	local decodedDate = date(decodedjson["Created"])
	placeFrame.CreationDate.Text =  "Created on " .. decodedDate.year .. "/" .. decodedDate.month .. "/" .. decodedDate.day
	placeFrame.PlaceName.Text = decodedjson["Name"]
	placeFrame.PlaceDescription.Text = decodedjson["Description"]
	placeFrame.PlaceVisits.Text = "Visits: " .. placevisits
	placeFrame.PlaceID.Text = "Place Id: " .. decodedjson["AssetId"]

	local rarity = getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	print(rarity)
	local rank = rarity.rarity
	local points = rarity.points
	placeFrame.Specials.TotalPoints.Text = "Total Points: " .. points .. "\nRanking: " .. rank
end

function roll()
	if canRoll == true then

		local decodedJSON = game.HttpService:JSONDecode(game.Players.LocalPlayer.dataStats.decodedPlaceJSON.Value)
		local visits = game.Players.LocalPlayer.dataStats.RecentRollVisits.Value
		setupPlace(decodedJSON, visits)
		script.Parent.RollButton.Text = "Rolling"
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice1.Image = "rbxassetid://" .. pickedSide
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice2.Image = "rbxassetid://" .. pickedSide
		game.ReplicatedStorage.RollPlace:FireServer() -- for next roll, so they dont have to wait as long
		canRoll = false
		if script.Parent.FastRollOn.Value == true then
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		else
			script.Parent.Dice1.BackgroundTransparency = 0
			script.Parent.Dice2.BackgroundTransparency = 0
			script.Parent.Dice1.ImageTransparency = 0
			script.Parent.Dice2.ImageTransparency = 0
			script.Parent.DiceRoll:Play()
			local dice1Tween1 = TweenService:Create(script.Parent.Dice1, TweenInfo.new(1), {Rotation = 360, Position = UDim2.new(0.584, 0,0.498, 0)})
			local dice2Tween1 = TweenService:Create(script.Parent.Dice2, TweenInfo.new(0.9), {Rotation = 450, Position = UDim2.new(0.681, 0,0.498, 0)})
			dice1Tween1:Play()
			dice2Tween1:Play()
			wait(0.8)
			script.Parent.Drumroll:Play()
			wait(1)
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		end
	end 
end

local function populateInventory()
	if currentTask then
		task.cancel(currentTask)
		currentTask = nil
	end
	
	local slots = script.Parent.InventoryFrame.Slots
	local games = parseString(game.Players.LocalPlayer.dataStats.CollectedGames.Value)
	local template = script.Template

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[item.Name] = true
		end
	end
	
	currentTask = task.spawn(function()
		for key, value in ipairs(games) do
			local decodedJSON = MarketPlaceService:GetProductInfo(value)

			local gameName = decodedJSON["Name"]
			local gameId = decodedJSON["AssetId"]

			if not existingItems[gameId] then
				local points = 0
				local decodedDate = date(decodedJSON["Created"])

				if decodedJSON["Creator"]["HasVerifiedBadge"] == true then
					points += 10
				end

				local placevisits = game.ReplicatedStorage.GetPlaceVisits:InvokeServer(gameId)

				if placevisits then
					if placevisits > 9999 then
						points += 25 
					end
				else
					warn("not working :/")
				end

				if tonumber(decodedDate.year) < 2010 then
					points += 15
				elseif tonumber(decodedDate.year) < 2014 then 
					points += 10
				end

				if decodedJSON["IconImageAssetId"] ~= 0 then
					points += 5
				end

				if string.find(decodedJSON["Name"], "Content Deleted", 1, true) then
					points += 1
				end

				if decodedJSON["AssetId"] == 17044556893 then
					-- HOW DID THEY ROLL THIS. THEY NEED 1 BILLION FOLLOWERS
					points += 500
				end

				local rank

				if points <= 5 then
					rank = "Common"
				elseif points <= 10 then
					rank = "Uncommon"
				elseif points <= 25 then
					rank = "Rare"
				elseif points <= 35 then
					rank = "Epic"
				elseif points <= 45 then
					rank = "Mythic"
				end

				local myGame = template:Clone()
				myGame.Name = gameId
				myGame.PlaceName.Text = gameName
				myGame.PlaceCreator.Text = decodedJSON["Creator"].Name
				myGame.PlaceIcon.Image = decodedJSON["IconImageAssetId"] == 0 and "rbxassetid://17055597657" or "rbxassetid://" .. decodedJSON["IconImageAssetId"]
				myGame.BackgroundColor3 = rarityColors[rank]
				myGame.PlaceId.Value = gameId
				myGame.Parent = slots
			end
		end
	end)
end


script.Parent.RollButton.Activated:Connect(roll)

script.Parent.InfoButton.Activated:Connect(function()
	script.Parent.Information.Visible = true
end)

script.Parent.Information.ExitButton.Activated:Connect(function()
	script.Parent.Information.Visible = false
end)

script.Parent.AutoRollButton.Activated:Connect(function()
	if script.Parent.AutoRollOn.Value == false then
		script.Parent.AutoRollOn.Value = true
		script.Parent.AutoRollButton.Text = "Auto Roll: On"
	else
		script.Parent.AutoRollOn.Value = false
		script.Parent.AutoRollButton.Text = "Auto Roll: Off"
	end
end)

script.Parent.InventoryButton.Activated:Connect(function()
	script.Parent.Loading.Visible = true
	populateInventory()
	script.Parent.Loading.Visible = false
	script.Parent.InventoryFrame.Visible = true

end)

script.Parent.InventoryFrame.ExitButton.Activated:Connect(function()
	script.Parent.InventoryFrame.Visible = false
end)

script.Parent.MoreLuckButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = true
end)

script.Parent.DevProducts.ExitButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = false
end)

script.Parent.FastRollButton.Activated:Connect(function()
	if MarketPlaceService:UserOwnsGamePassAsync(game.Players.LocalPlayer.UserId, 777801444) then
		if script.Parent.FastRollOn.Value == false then
			script.Parent.FastRollOn.Value = true
			script.Parent.FastRollButton.Text = "Fast Roll: On"
		else
			script.Parent.FastRollOn.Value = false
			script.Parent.FastRollButton.Text = "Fast Roll: Off"
		end
	else
		MarketPlaceService:PromptGamePassPurchase(game.Players.LocalPlayer, 777801444)
	end
end)
script.Parent.PurchaseAllFrontPageGames.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = true
end)

script.Parent.PopularGamesPack.ExitButton.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = false
end)
for _, item in pairs(script.Parent:GetDescendants()) do
	if item:IsA("TextButton") or item:IsA("ImageButton") then
		local soundScript = script.ButtonSound:Clone()
		soundScript.Parent = item
		soundScript.Enabled = true
	end
end

while true do
	if script.Parent.AutoRollOn.Value == true then
		roll()
	else
		script.Parent.AutoRollOn.Changed:Wait()
	end
end

I just tried this script. It’s slow and when I go to the inventory again, it doesn’t clear the previous time you opened it.

I’ve thought of a new idea to load the table when the inventory isn’t loaded.

Tell me if this works:

local TweenService = game:GetService("TweenService")
local MarketPlaceService = game:GetService("MarketplaceService")
local diceSides = {
	11105170518, -- 1
	11105171156, -- 2
	11105171911, -- 3
	11105172844, -- 4
	11105173494, -- 5
	11105173941 -- 6
}

local games = {}
local rarityColors = {
	["Common"] = Color3.fromRGB(68, 68, 68),
	["Uncommon"] = Color3.fromRGB(102, 100, 94),
	["Rare"] = Color3.fromRGB(70, 182, 70),
	["Epic"] = Color3.fromRGB(48, 97, 234),
	["Legendary"] = Color3.fromRGB(255, 243, 79),
	["Mythic"] = Color3.fromRGB(142, 56, 229)
}
local pickedSide

local canRoll = true

game.ReplicatedStorage.RollPlace:FireServer()

function date(str)
	local data = {}
	local y,m,d,h,i,s,t=str:match"(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).(%d+)Z"
	data.year=y data.month=m data.day=d data.hour=h data.min=i data.sec=s data.milli=t
	data.sinceEpoch=os.time(data)
	return data
end

function parseString(inputString)
	local dictionary = {}
	for number in inputString:gmatch("[^,]+") do
		table.insert(dictionary, tonumber(number))
	end
	return dictionary
end

function getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	if decodedjson["Creator"]["HasVerifiedBadge"] == true then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Creator is verified."
		game.ReplicatedStorage.GimmehBadge:FireServer(1443573582565408)
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if placevisits > 9999 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +25 Points. Has more than 10k visits."
		placeFrame.Specials.TotalPointsV.Value += 25
		game.ReplicatedStorage.GimmehBadge:FireServer(2689485152267094)
	end	

	if tonumber(decodedDate.year) < 2010 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +15 Points. Made before 2010"
		placeFrame.Specials.TotalPointsV.Value += 15
		game.ReplicatedStorage.GimmehBadge:FireServer(1391843739894243)
	elseif tonumber(decodedDate.year) < 2014 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +10 Points. Made before 2014"
		placeFrame.Specials.TotalPointsV.Value += 10
	end
	if decodedjson["IconImageAssetId"] ~= 0 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +5 Points. Has a custom icon."
		placeFrame.Specials.TotalPointsV.Value += 5
	end
	if string.find(decodedjson["Name"], "Content Deleted", 1, true) then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +1 Point. Is content deleted."
		placeFrame.Specials.TotalPointsV.Value += 1
		game.ReplicatedStorage.GimmehBadge:FireServer(1107810746136549)
	end 
	if decodedjson["AssetId"] == 17044556893 then
		placeFrame.Specials.Special.Text = placeFrame.Specials.Special.Text .. " +500 Points. You rolled game rng!! HOW?"
		placeFrame.Specials.TotalPointsV.Value += 500
		game.ReplicatedStorage.GimmehBadge:FireServer(581872078322536)
	end

	local rank

	if placeFrame.Specials.TotalPointsV.Value <= 5 then
		rank = "Common"
	elseif placeFrame.Specials.TotalPointsV.Value <= 10 then
		rank = "Uncommon"
	elseif placeFrame.Specials.TotalPointsV.Value <= 25 then
		rank = "Rare"
	elseif placeFrame.Specials.TotalPointsV.Value <= 35 then
		rank = "Epic"
	elseif placeFrame.Specials.TotalPointsV.Value <= 45 then
		rank = "Mythic"
		game.ReplicatedStorage.GlobalMessage:FireServer(rank)
	end
	local data = {
		rarity = rank,
		points = placeFrame.Specials.TotalPointsV.Value
	}
	return data
end

function setupPlace(decodedjson, placevisits)
	local placeFrame = script.Parent.PlaceUnlock
	if decodedjson["IconImageAssetId"] == 0 then
		placeFrame.PlaceIcon.Image = "rbxassetid://17055597657"
	else
		placeFrame.PlaceIcon.Image = "rbxassetid://" .. decodedjson["IconImageAssetId"]
		print("Icon Asset Id: " .. decodedjson["IconImageAssetId"])
		placeFrame.DefaultIconNotice.Visible = false
	end
	placeFrame.Specials.Special.Text = " "
	placeFrame.Specials.TotalPointsV.Value = 0
	placeFrame.CreatorName.Text = "Created by " .. decodedjson["Creator"].Name
	local decodedDate = date(decodedjson["Created"])
	placeFrame.CreationDate.Text =  "Created on " .. decodedDate.year .. "/" .. decodedDate.month .. "/" .. decodedDate.day
	placeFrame.PlaceName.Text = decodedjson["Name"]
	placeFrame.PlaceDescription.Text = decodedjson["Description"]
	placeFrame.PlaceVisits.Text = "Visits: " .. placevisits
	placeFrame.PlaceID.Text = "Place Id: " .. decodedjson["AssetId"]

	local rarity = getRarity(decodedjson, decodedDate, placevisits, placeFrame)
	print(rarity)
	local rank = rarity.rarity
	local points = rarity.points
	placeFrame.Specials.TotalPoints.Text = "Total Points: " .. points .. "\nRanking: " .. rank
end

function roll()
	if canRoll == true then

		local decodedJSON = game.HttpService:JSONDecode(game.Players.LocalPlayer.dataStats.decodedPlaceJSON.Value)
		local visits = game.Players.LocalPlayer.dataStats.RecentRollVisits.Value
		setupPlace(decodedJSON, visits)
		script.Parent.RollButton.Text = "Rolling"
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice1.Image = "rbxassetid://" .. pickedSide
		pickedSide = diceSides[math.random(1, 6)]
		script.Parent.Dice2.Image = "rbxassetid://" .. pickedSide
		game.ReplicatedStorage.RollPlace:FireServer() -- for next roll, so they dont have to wait as long
		canRoll = false
		if script.Parent.FastRollOn.Value == true then
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		else
			script.Parent.Dice1.BackgroundTransparency = 0
			script.Parent.Dice2.BackgroundTransparency = 0
			script.Parent.Dice1.ImageTransparency = 0
			script.Parent.Dice2.ImageTransparency = 0
			script.Parent.DiceRoll:Play()
			local dice1Tween1 = TweenService:Create(script.Parent.Dice1, TweenInfo.new(1), {Rotation = 360, Position = UDim2.new(0.584, 0,0.498, 0)})
			local dice2Tween1 = TweenService:Create(script.Parent.Dice2, TweenInfo.new(0.9), {Rotation = 450, Position = UDim2.new(0.681, 0,0.498, 0)})
			dice1Tween1:Play()
			dice2Tween1:Play()
			wait(0.8)
			script.Parent.Drumroll:Play()
			wait(1)
			script.Parent.PlaceUnlock.Visible = true
			script.Parent.Dice1.BackgroundTransparency = 1
			script.Parent.Dice2.BackgroundTransparency = 1
			script.Parent.Dice1.Rotation = 0
			script.Parent.Dice2.Rotation = 0
			script.Parent.Dice1.ImageTransparency = 1
			script.Parent.Dice2.ImageTransparency = 1
			script.Parent.Dice1.Position = UDim2.new(0.033, 0,0.438, 0)
			script.Parent.Dice2.Position = UDim2.new(0,0,0.597,0)
			script.Parent.Reveal:Play()
			wait(3)
			local placeunlocktween = TweenService:Create(script.Parent.PlaceUnlock, TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false), {Position = UDim2.new(-2,0,0.249,0)})
			placeunlocktween:Play()
			game.ReplicatedStorage.SaveData:FireServer(decodedJSON["AssetId"])
			placeunlocktween.Completed:Wait()
			script.Parent.PlaceUnlock.Visible = false
			script.Parent.PlaceUnlock.Position = UDim2.new(0.194,0,0.249,0)
			script.Parent.RollButton.Text = "Roll"
			canRoll = true
		end
	end 
end

local infoCache = {}

game:GetService("Players").LocalPlayer:WaitForChild("dataStats").CollectedGames.Changed:Connect(function(newValue)
	local parsedString = parseString(newValue)
	local tempTable = {}
	
	for i, value in parsedString do
		local productInfo = infoCache[value] or MarketPlaceService:GetProductInfo(value)
		
		if not infoCache[value] then
			infoCache[value] = productInfo
		end
		
		tempTable[i] = productInfo
	end
	
	games = table.clone(tempTable)
end)

local function populateInventory()
	local slots = script.Parent.InventoryFrame.Slots
	local template = script.Template

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[item.Name] = true
		end
	end
	
	for _, decodedJSON in ipairs(games) do
		local gameName = decodedJSON["Name"]
		local gameId = decodedJSON["AssetId"]

		if not existingItems[gameId] then
			local points = 0
			local decodedDate = date(decodedJSON["Created"])

			if decodedJSON["Creator"]["HasVerifiedBadge"] == true then
				points += 10
			end

			local placevisits = game.ReplicatedStorage.GetPlaceVisits:InvokeServer(gameId)

			if placevisits then
				if placevisits > 9999 then
					points += 25 
				end
			else
				warn("not working :/")
			end

			if tonumber(decodedDate.year) < 2010 then
				points += 15
			elseif tonumber(decodedDate.year) < 2014 then 
				points += 10
			end

			if decodedJSON["IconImageAssetId"] ~= 0 then
				points += 5
			end

			if string.find(decodedJSON["Name"], "Content Deleted", 1, true) then
				points += 1
			end

			if decodedJSON["AssetId"] == 17044556893 then
				-- HOW DID THEY ROLL THIS. THEY NEED 1 BILLION FOLLOWERS
				points += 500
			end

			local rank

			if points <= 5 then
				rank = "Common"
			elseif points <= 10 then
				rank = "Uncommon"
			elseif points <= 25 then
				rank = "Rare"
			elseif points <= 35 then
				rank = "Epic"
			elseif points <= 45 then
				rank = "Mythic"
			end

			local myGame = template:Clone()
			myGame.Name = gameId
			myGame.PlaceName.Text = gameName
			myGame.PlaceCreator.Text = decodedJSON["Creator"].Name
			myGame.PlaceIcon.Image = decodedJSON["IconImageAssetId"] == 0 and "rbxassetid://17055597657" or "rbxassetid://" .. decodedJSON["IconImageAssetId"]
			myGame.BackgroundColor3 = rarityColors[rank]
			myGame.PlaceId.Value = gameId
			myGame.Parent = slots
		end
	end
end


script.Parent.RollButton.Activated:Connect(roll)

script.Parent.InfoButton.Activated:Connect(function()
	script.Parent.Information.Visible = true
end)

script.Parent.Information.ExitButton.Activated:Connect(function()
	script.Parent.Information.Visible = false
end)

script.Parent.AutoRollButton.Activated:Connect(function()
	if script.Parent.AutoRollOn.Value == false then
		script.Parent.AutoRollOn.Value = true
		script.Parent.AutoRollButton.Text = "Auto Roll: On"
	else
		script.Parent.AutoRollOn.Value = false
		script.Parent.AutoRollButton.Text = "Auto Roll: Off"
	end
end)

script.Parent.InventoryButton.Activated:Connect(function()
	script.Parent.Loading.Visible = true
	populateInventory()
	script.Parent.Loading.Visible = false
	script.Parent.InventoryFrame.Visible = true

end)

script.Parent.InventoryFrame.ExitButton.Activated:Connect(function()
	script.Parent.InventoryFrame.Visible = false
end)

script.Parent.MoreLuckButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = true
end)

script.Parent.DevProducts.ExitButton.Activated:Connect(function()
	script.Parent.DevProducts.Visible = false
end)

script.Parent.FastRollButton.Activated:Connect(function()
	if MarketPlaceService:UserOwnsGamePassAsync(game.Players.LocalPlayer.UserId, 777801444) then
		if script.Parent.FastRollOn.Value == false then
			script.Parent.FastRollOn.Value = true
			script.Parent.FastRollButton.Text = "Fast Roll: On"
		else
			script.Parent.FastRollOn.Value = false
			script.Parent.FastRollButton.Text = "Fast Roll: Off"
		end
	else
		MarketPlaceService:PromptGamePassPurchase(game.Players.LocalPlayer, 777801444)
	end
end)
script.Parent.PurchaseAllFrontPageGames.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = true
end)

script.Parent.PopularGamesPack.ExitButton.Activated:Connect(function()
	script.Parent.PopularGamesPack.Visible = false
end)
for _, item in pairs(script.Parent:GetDescendants()) do
	if item:IsA("TextButton") or item:IsA("ImageButton") then
		local soundScript = script.ButtonSound:Clone()
		soundScript.Parent = item
		soundScript.Enabled = true
	end
end

while true do
	if script.Parent.AutoRollOn.Value == true then
		roll()
	else
		script.Parent.AutoRollOn.Changed:Wait()
	end
end

Edited it to cache right now

The cache idea that @Katrist suggested is the way to go. In fact, it works perfectly fine for me. I think the reason as to why it ends up being the “same speed” is because you have a RemoteFunction which yields for each index. Depending on the code inside of the OnServerInvoke function, that could be your answer as to why.

game.ReplicatedStorage.GetPlaceVisits.OnServerInvoke = function(player, placeid)
	return GetGameData("Visits", placeid)
end
function GetGameData(TypeOfData, PlaceId)
	local universeId = HTTPService:JSONDecode(HTTPService:GetAsync("https://apis.roproxy.com/universes/v1/places/" .. PlaceId .. "/universe"))["universeId"]
	print(universeId)
	if TypeOfData == "Visits" then
		local success, json = pcall(function()
			return HTTPService:GetAsync("https://games.roproxy.com/v1/games?universeIds=" .. universeId)
		end)

		if success then
			local response = HTTPService:JSONDecode(json)
			local visits = response.data[1].visits
			return visits
		end
	end

Well, there’s your answer. HttpService:GetAsync() can take a while depending on what is being requested. Especially since you’re using it twice here. Add that on top of the fact that it’s a function tied to a RemoteFunction event and it becomes clear as to why it remains the same speed. You can just cache the result given back to the client inside of the infoCache[value] table as well:

-- Assuming infoCache is an empty table defined somewhere
function populateInventory()
	local slots = script.Parent.InventoryFrame.Slots
	local games = parseString(game.Players.LocalPlayer.dataStats.CollectedGames.Value)
	local template = script.Template

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[item.Name] = true
		end
	end

	for key, value in ipairs(games) do
		local decodedJSON = infoCache[value] or MarketPlaceService:GetProductInfo(value)
		infoCache[value] = decodedJSON -- Set the value to be decodedJSON in the event infoCache[value] does not exist
		local gameName = decodedJSON["Name"]
		local gameId = decodedJSON["AssetId"]

		if not existingItems[gameId] then
			local points = 0
			local decodedDate = date(decodedJSON["Created"])
			if decodedJSON["Creator"]["HasVerifiedBadge"] == true then
				points += 10
			end
			local placevisits = decodedJSON.Visits or game.ReplicatedStorage.GetPlaceVisits:InvokeServer(gameId)
			if placevisits then
				decodedJSON.Visits = placevisits
				print(placevisits)
				if placevisits > 9999 then
					points += 25 
				end
			else
				warn("not working :/")
			end
			if tonumber(decodedDate.year) < 2010 then
				points += 15
			elseif tonumber(decodedDate.year) < 2014 then 
				points += 10
			end
			if decodedJSON["IconImageAssetId"] ~= 0 then
				points += 5
			end
			if string.find(decodedJSON["Name"], "Content Deleted", 1, true) then
				points += 1
			end
			if decodedJSON["AssetId"] == 17044556893 then
				-- HOW DID THEY ROLL THIS. THEY NEED 1 BILLION FOLLOWERS
				points += 500
			end
			local rank

			if points <= 5 then
				rank = "Common"
			elseif points <= 10 then
				rank = "Uncommon"
			elseif points <= 25 then
				rank = "Rare"
			elseif points <= 35 then
				rank = "Epic"
			elseif points <= 45 then
				rank = "Mythic"
			end
			
			

			local myGame = template:Clone()
			myGame.PlaceName.Text = gameName
			if decodedJSON["IconImageAssetId"] == 0 then
				myGame.PlaceIcon.Image = "rbxassetid://17055597657"
			else
				myGame.PlaceIcon.Image = "rbxassetid://" .. decodedJSON["IconImageAssetId"]
			end
			myGame.PlaceCreator.Text = decodedJSON["Creator"].Name
			myGame.Parent = slots
			myGame.Name = gameId
			myGame.BackgroundColor3 = rarityColors[rank]
			myGame.PlaceId.Value = gameId
		end
	end
end

seems to work but when i open the inventory the second time, it just puts all the tables values into the inventory again, even if they are already in it.

It’s probably due to the fact that item.Name would be a string:

But since gameId is of the number datatype, it doesn’t match when you index the existingItems table:

You can either use tonumber() or tostring() – depending on which one you want to change:

Case 1:

	local existingItems = {}
	for _, item in ipairs(slots:GetChildren()) do
		if not item:IsA("UIGridLayout") then
			existingItems[tonumber(item.Name)] = true
		end
	end

Case 2:

		local gameName = decodedJSON["Name"]
		local gameId = decodedJSON["AssetId"]

		if not existingItems[tostring(gameId)] then

Make sure you only do one or the other, not both.

tysm!!! it works perfectly

extracharacters