Edit: Clarification
interestingly, when I copied and pasted the code into my Roblox Studio, it worked perfectly. Somehow.
There are a couple things I want to point out about the code.
First, I agree with everyone that the variable names could be improved for reading. Usually that’s fine when only you have to read the code, but in this case it’s hard to read when trying to help you. The best practice is always to write your code like you will have to show someone else.
Second, Never use a global local variable (singular memory location) to store a players data. If two players join the game, the second player to join will override the n variable. You need to create a new variable (new memory location) for each player’s data, so data does not get overwritten. The easiest way is to put the data into a table.
Finally, as @PolyLacticSugarcane said, it could be that there is not enough time to save when you exit, and the server automatically starts to shut down. However, there may be cases where even 5 extra seconds are not enough (though usually it is). One thing you can do to always ensure data saves is to keep a counter for how many people still need to save when the server starts shutting down and waiting until that counter hits 0.
Here’s your code updated (in your syntax mostly) with some quick fixes.
local dss = game:GetService("DataStoreService")
local d = dss:GetDataStore("number")
local nList = {}
local playersNeedingSaved = 0
local function key(p)
return "number" .. p.UserId
end
local function load(p)
local pkey = key(p)
local success, number = pcall(function()
return d:GetAsync(pkey)
end)
if success then
return number or 0
else
warn("didnt load")
return 0
end
end
local function save(p, value)
local pkey = key(p)
local success, errorMessage = pcall(function()
d:SetAsync(pkey, value)
end)
if not success then
warn("didnt save")
end
end
game.Players.PlayerAdded:Connect(function(p)
nList[p.UserId] = load(p)
local n = nList[p.UserId]
if n == nil then
n = 1
nList[p.UserId] = n
end
playersNeedingSaved += 1
print(p.Name, n)
end)
local function add(p)
local n = nList[p.UserId]
n = n + 1
nList[p.UserId] = nil
save(p, n)
end
local function onLeave(p)
add(p)
playersNeedingSaved -= 1
end
game:BindToClose(function()
while playersNeedingSaved > 0 do
task.wait(.25)
end
end)
game.Players.PlayerRemoving:Connect(onLeave)
Though in the end my biggest recommendation is to just randomly select a starting dialogue when the player joins, and not worry about if it chooses the same one twice in a row. Simpler, and way more reliable with only minimal downsides.