GlobalDatastores ListKeyAsync() Broken? [3rd time posting still no help]

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want to announce “Choosing a random question from” … numberofquestions_in_questionsdatabase
  2. What is the issue? Include screenshots / videos if possible!
    I added only 3 questions and i even tried adding one more but everytime it announce choosing a random question from 13 questions.
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried looking it everywhere and using chatgpt but cant understand the problem.
local Replicated_Storage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local TextService = game:GetService("TextService")

local DataStoreService = game:GetService("DataStoreService")

local Dares = DataStoreService:GetGlobalDataStore("DaresV1")
local Questions = DataStoreService:GetGlobalDataStore("QuestionsV1")

local Modules = Replicated_Storage:WaitForChild("Modules")
local Remotes = Replicated_Storage:WaitForChild("Remotes")
local Announce = Remotes:WaitForChild("Announce")
local TruthOrDare = Remotes:WaitForChild("TruthOrDare")
local Vote = Remotes:WaitForChild("Vote")
local ServerMessage = Remotes:WaitForChild("ServerMessage")
local Bottle = workspace:WaitForChild("Boba")
	local Bottle_Sounds = Bottle:WaitForChild("Sounds")

local Sessions = require(script.Parent.Sessions)
local Seats_Session = Sessions.Seat_Sessions

local Dares_Folder = workspace.Forest_Map.Dares

local Playing = true

local Chairs_Rotation_Thing = {
	["Chair1"] = 75,
	["Chair2"] = 30,
	["Chair3"] = -15,
	["Chair4"] = -60,
	["Chair5"] = -105,
	["Chair6"] = -150,
	["Chair7"] = 165,
	["Chair8"] = 120
}

local Seats = workspace.Forest_Map.Shack.Main.Chairs
local NameTags = Replicated_Storage:WaitForChild("NameTags")

for ind,chair in pairs(Seats:GetChildren()) do
	chair.Seat:GetPropertyChangedSignal("Occupant"):Connect(function()
		if chair.Seat.Occupant ~= nil then
			local Char = chair.Seat.Occupant.Parent
			local plr = game.Players:FindFirstChild(Char.Name)

			if Char and plr and Char:FindFirstChild('Humanoid') then
				table.insert(Seats_Session, plr)
				Char.Humanoid.JumpPower = 0
			end			
		end
	end)
end
for ind, dare in pairs(Dares_Folder:GetChildren()) do
	if dare:FindFirstChild("End") then
		dare.End.Touched:Connect(function()
			Remotes.Spectate:FireAllClients("End", nil)
		end)
	end
end

function spin(chair)
	local tweenService: TweenService = game:GetService("TweenService")

	local tween: Tween = tweenService:Create(Bottle, TweenInfo.new(1, Enum.EasingStyle.Circular), {
		Orientation = Bottle.Orientation + Vector3.new(0, 0, 1080)
	})
	
	local tween3: Tween = tweenService:Create(Bottle, TweenInfo.new(.5, Enum.EasingStyle.Circular), {
		Orientation = Bottle.Orientation + Vector3.new(0, 0, 75)
	})
	
	local tween2 = tweenService:Create(Bottle, TweenInfo.new(0.5, Enum.EasingStyle.Circular), {
		Orientation = Vector3.new(-89,-168, Chairs_Rotation_Thing[chair])
	})

	tween:Play()
	
	
	task.wait(0.65)
	--tween3:Play()
	--task.wait(0.6)
	--print('tween3 completed playing tween 2')
	tween2:Play()
	task.wait(1)
	
	task.wait(0.6)
end

local choosen_player = nil
local response = nil
local voting = false
local Votes = {}

TruthOrDare.OnServerEvent:Connect(function(player, msg)
	if response == nil and player == choosen_player then
		if msg == "Truth" then
			response = "Truth"
		elseif msg == "Dare" then
			response = "Dare"
		end
	end
end)

function checkvote(player)
	for i, vote in pairs(Votes) do
		if i == player.Name then
			return true
		end
	end
	return false
end

Vote.OnServerEvent:Connect(function(player, val)
	if player ~= choosen_player and voting and checkvote(player) == false then -- check vote = false mean dosent find player in Votes
		if val == true then
			Votes[player.Name] = true
		elseif val == false then
			Votes[player.Name] = false
		end
	end
end)


function StartVotes()
	if game.PrivateServerId == "" and game.PrivateServerOwnerId == 0 and #game.Players:GetPlayers() >= 3 then
		table.clear(Votes)
		voting = true
		Vote:FireAllClients()
		Bottle_Sounds.Clock_Ticking.Playing = true

		for i = -15, 0 do
			Announce:FireAllClients("Votes end in " .. math.abs(i) .. " seconds.")
			wait(1)
		end
		Bottle_Sounds.Clock_Ticking.Playing = false
		wait(0.25)

		local trueVotes = 0
		local falseVotes = 0

		for playerName, vote in pairs(Votes) do
			if vote == true then
				trueVotes = trueVotes + 1
			else
				falseVotes = falseVotes + 1
			end
		end

		local totalVotes = trueVotes + falseVotes

		if falseVotes > (totalVotes / 2) then
			local falsePercentage = (falseVotes / totalVotes) * 100
			Announce:FireAllClients("Majority voted false (" .. string.format("%.2f", falsePercentage) .. "%)")
		else
			local truePercentage = (trueVotes / totalVotes) * 100
			Announce:FireAllClients("Majority voted true (" .. string.format("%.2f", truePercentage) .. "%)")
		end
		Bottle_Sounds.Response:Play()
		wait(5)
	elseif game.PrivateServerId ~= "" and game.PrivateServerOwnerId ~= 0 then
		Announce:FireAllClients("Votes Are Disabled In Private Servers.")
	elseif #game.Players:GetPlayers() < 3 then
		Announce:FireAllClients("Not Enough Players To Vote.")
	end
end



function checkifplayer(player)
	if table.find(Seats_Session, player) then
		return true
	end
	return false
end

local questionning = false
local responded = false

local last_player = nil
local choosen_tag = nil

game.Players.PlayerAdded:Connect(function(plr)
	plr.Chatted:Connect(function(chat)
		if plr == choosen_player and questionning then
			responded = chat
		end
	end)
end)

function intialize()
	if choosen_tag then
		choosen_tag:Destroy()
	end
	response = nil
	choosen_player = nil
	responded = false
	questionning = false
	voting = false
	table.clear(Votes)
end

while true do
	if #Seats_Session > 1 then
		Bottle_Sounds.Clock_Ticking.Playing = true
		for i=-5,0 do 
			Announce:FireAllClients("Next Player Getting Choosen in "..math.abs(i).." seconds")
			wait(1)
			if Playing == false then
				break
			end
		end
		
		Bottle_Sounds.Clock_Ticking.Playing = false
		local function ChoosePlayer()
			local playing = #Seats_Session
			local rdm_player = math.random(1, playing)

			local choosen_player = Seats_Session[rdm_player]

			return choosen_player
		end
		
		repeat
			choosen_player = ChoosePlayer()
		until last_player ~= choosen_player

		last_player = choosen_player
		
		for ind, chair in pairs(Seats:GetChildren()) do
			if chair.Seat.Occupant ~= nil then
				
				local Char = chair.Seat.Occupant.Parent
				local plr = game.Players:FindFirstChild(Char.Name)

				if Char and plr and plr.Name == choosen_player.Name then
					spin(chair.Name)
					
					Bottle_Sounds.Response:Play()
					
					choosen_tag = NameTags.Choosen:Clone()
					choosen_tag.Parent = Char.Head

					Announce:FireAllClients("Truth or Dare ? "..choosen_player.Name..".")	
					TruthOrDare:FireClient(choosen_player)

					Bottle_Sounds.Clock_Ticking.Playing = true
					
					local Attempts = 0
					
					repeat
						wait(1)
						Attempts += 1
						Announce:FireAllClients("Truth or Dare ? "..choosen_player.Name..". (".. 15 - Attempts ..")")
						if Attempts == 15 then
							Announce:FireAllClients(choosen_player.Name.." Took too much time to respond.")
							break
						elseif choosen_player == nil then
							Announce:FireAllClients("Player left the game. He will be punished.")
							break
						elseif checkifplayer(choosen_player) == false then
							Announce:FireAllClients("Choosen player has left the table.")
							break
						elseif #Seats_Session < 2 then
							Announce:FireAllClients("Not Enough Players To Continue this round.")
							break
						end

					until response ~= nil
					
					if response == nil then
						Announce:FireAllClients("Player Took Too Much Time To Choose.")
					end
					
					Bottle_Sounds.Clock_Ticking.Playing = false
					
					if response ~= nil and Attempts < 15 and choosen_player ~= nil and table.find(Seats_Session, choosen_player) then
						Announce:FireAllClients(choosen_player.Name.." Chose "..string.upper(response)..".")
						ServerMessage:FireAllClients(choosen_player.Name.." Chose "..string.upper(response)..".")
						Bottle_Sounds.Response:Play()
						
						wait(2)

						if response == "Truth" then
							local pages = Questions:ListKeysAsync(nil, 100)
							local counter = 0
							while true do
								for _, key in pairs(pages:GetCurrentPage()) do
									counter += 1
									warn(key.KeyName)
								end
								if pages.IsFinished then
									break	-- Exit loop if we've looped over all pages
								end
								-- Get new page (same API limit as calling 'ListKeysAsync')
								pages:AdvanceToNextPageAsync()
							end

							Announce:FireAllClients("Picking a Random Question from "..counter.." Questions.")
							
							wait(3)
							
							local randomIndex = math.random(1, counter)

							local success5, errormsg5 = nil, nil 
							local attempt5 = 1 -- how many attemps

							repeat -- attempt to get data
								success5, entity = pcall(function()
									return Questions:GetAsync(randomIndex)
								end)
								attempt5 += 1
								if not success5 then
									warn(entity)
									task.wait(3)
								end
							until success5 or attempt5 == 5

							warn(entity)

							if checkifplayer(choosen_player) == true then
								questionning = true
								Announce:FireAllClients(choosen_player.Name .. "... " .. tostring(entity))
								ServerMessage:FireAllClients(choosen_player.Name .. "... " .. tostring(entity))
								for i=-70, 0 do
									Announce:FireAllClients(choosen_player.Name .. "... " .. tostring(entity) .. "(".. math.abs(i) .. ")")
									
									if checkifplayer(choosen_player) == false or responded then	questionning = false break end
									wait(1)
								end
								
								if checkifplayer(choosen_player) and responded ~= false then
									wait(1)
									Announce:FireAllClients(choosen_player.Name.." Responded : ".. responded)
									ServerMessage:FireAllClients(choosen_player.Name.." Responded : ".. responded)
									
									-- feature to make players vote if they should give him gems
									wait(8)
								end
							else
								intialize()
								break
							end


						elseif response == "Dare" then							
							local pages = Dares:ListKeysAsync(nil, 100)
							local counter = 0
							while true do
								for _, key in pairs(pages:GetCurrentPage()) do
									counter += 1
									warn(key.KeyName)
								end
								if pages.IsFinished then
									break	-- Exit loop if we've looped over all pages
								end
								-- Get new page (same API limit as calling 'ListKeysAsync')
								pages:AdvanceToNextPageAsync()
							end

							Announce:FireAllClients("Picking a Random Dare from "..counter.." Dares.")
							
							wait(3)
							
							local randomIndex = math.random(1, counter)

							local success5, errormsg5 = nil, nil 
							local attempt5 = 1 -- how many attemps
							
							repeat -- attempt to get data
								success5, entity = pcall(function()
									return Dares:GetAsync(randomIndex)
								end)
								attempt5 += 1
								if not success5 then
									warn(entity)
									task.wait(3)
								end
							until success5 or attempt5 == 5
							
							
							warn(entity)
							local dare_object = string.split(entity, " | ")[2]
								local dare_spawn = Dares[dare_object].Spawn
							choosen_player.Character.HumanoidRootPart.CFrame = CFrame.new(dare_spawn.Position.X, dare_spawn.Position.Y, dare_spawn.Position.Z)
							Remotes.Spectate:FireAllClients("Start", choosen_player)
							
						end
					end
					
					StartVotes()
					wait(5)
					Announce:FireAllClients("Starting a New Round...")
					
					intialize()
					break
				end
			end
		end
	else
		Announce:FireAllClients("Waiting for more players to start...")
		task.spawn(function()
			spin("Chair1")
		end)
	end
	wait(3)
end

So you can see that the datastores are globaldatastores and what i’m doing is, i’m saving questions in a Questions global datastore and Dares in a Dares global datastore and then what i do is listkeyasync from it’s datastore and count the keys in it then announce getting a random question from counted keys questions.
Btw the game is a Truth or Dare game and this script is a RoundManager script.

I posted this 2 times almost already but didn’t even explained it well and no one has helped so far.

1 Like

why are the questions being stored in a datastore? it wouldnt make much sense

anyway, for your code not working, i think it is because the datastore does not get updated when you call the list keys async event

1 Like

Damn i hate this type of people did you ready carefully ? i said my code is working the problem is with the global datastore basically i count all the keys in the global datastore using ListKeysAsync() then it says there is 13 keys even tho there is 4

At the top of your script, you’ve used DataStoreService:GetGlobalDataStore(), which fetches the singleton GlobalDataStore for the game, meaning both “Dares” and “Questions” are currently the same DataStore. Anything you’ve added to one you’ve added to both. To resolve this, use DataStoreService:GetDataStore() instead.

oh so you can have only one globaldatastore ? and i can do like getglobaldatastore.Dares or Getglobaldatastore.Questions for it instead ?

You can only have one GlobalDataStore, but you can have as many normal DataStores as you’d like, which is what you need in this case.

You just need to replace DataStoreService:GetGlobalDataStore with DataStoreService:GetDataStore to get normal DataStores instead of the global one, but you’ll also need to re-add your entries to their respective destinations since they’ll stay behind in the GlobalDataStore.

You don’t understand i need globaldatastores because i save questions and dares not player datas i also save the questions like
GDatastore:SetAsync(1, “question”)

GDatastoreListKeyAsync() – until finding the last key

then again :

GDatastore:SetAsync(2, “question”)

then i use math.random to get a key from 1, maxkeysnumber

sorry, i must have misread your post.

1 Like

DataStores are a subclass of GlobalDataStore. Both can hold the same types of data, and DataStores are not limited to just storing player data. They are suitable for your use case.

Yeah but you can’t ListKeyAsync() in Datastores

ListKeysAsync() is a method of the DataStore class, so you are able to use it on them.

as i remember last time that i tried using that it didnt worked and it returned nil

i will try again and i’ll tell you if it works or no in 2 hrs thank you for your help

Omg thank you it works i’ve been trying for weeks now you saved me. TYSM

1 Like

btw this is a serverside code for my game idk if i should let it here because everyone can see it.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.