Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

DataStore Is Not Saving Properly?

Asked by 6 years ago
Edited 6 years ago

Hello,

Problem: My DataStore is not saving the Leaderstats or the Tools once a player leaves/returns to the Game.

Information: When a player makes a purchase, the RemoteEvent fires up, enabling the BoolValues for the Tools to be True. The BoolValues are located inside a Folder named "Inventory" inside the player's Backpack. And there's a script thats set to clone the Tools into the StarterGear and Backpack. That part all seems to work perfectly. Its when the player leaves a game and returns, that the data is not being saved. There's no Output showing that the DataStore has failed, and I made sure the API Services were enabled.

The DataStore script is a Module Script inside ServerScriptService.

Any idea how to fix this to function properly?

My Module Script is below:

local module = {}
local DataStoreService = game:GetService("DataStoreService")
local InventoryItems = DataStoreService:GetDataStore("TEST")
AUTOSAVE_INTERVAL = 120

game.Players.PlayerAdded:Connect(function(Player)
local Key = "PlayerIdNum-"..Player.UserId.."_ToolItems"

--leaderstats
local inew = Instance.new
local ls = inew("Folder")

    ls.Name = "leaderstats"
    ls.Parent = Player

local points = inew("IntValue")
    points.Name = "Points"
    points.Value = 0
    points.Parent = ls

local experience = inew("IntValue")
    experience.Name = "Experience"
    experience.Value = 0
    experience.Parent = ls

local level = inew("IntValue")
    level.Name = "Level"
    level.Value = 1
    level.Parent = ls 

--Inventory
local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory")
local HasGun = InvData:WaitForChild("HasGun")

--Saving Data
local StoreToSet = {}
local DataToGet = InventoryItems:GetAsync(Key)
    if DataToGet ~= nil then
    if #DataToGet >= 1 then
    if DataToGet[1] ~= nil then
    HasGun.Value = DataToGet[1]
        table.insert(StoreToSet, DataToGet[1])
else

DataToGet[1] = HasGun.Value
    HasGun.Value = false
        table.insert(StoreToSet, DataToGet[1])
end
end

else

DataToGet = {}
DataToGet[1] = HasGun.Value
    HasGun.Value = false
        table.insert(StoreToSet, DataToGet[1])

print("New Data")
end

InventoryItems:SetAsync(Key, StoreToSet)
repeat wait() until Player.Character

if Player.Character and Player.Character:FindFirstChild("Humanoid") then
Player.Character.Humanoid.MaxHealth = 100 + (level.Value*10)

end

level.Changed:Connect(function(value)
if Player.Character and Player.Character:FindFirstChild("Humanoid") then
    Player.Character.Humanoid.MaxHealth = 100 + (level.Value*10)
end
end)

Player.CharacterAdded:Connect(function(character)
    character:WaitForChild("Humanoid").MaxHealth = 100 + (level.Value*10)

end)

local required = (level.Value*70)

experience.Changed:Connect(function()
    if experience.Value >= required then
        level.Value=level.Value+1
        experience.Value = experience.Value-required

end
end)
end)


-- PLAYER REMOVING


game.Players.PlayerRemoving:Connect(function(Player)

local Key = "PlayerIdNum-"..Player.UserId.."_ToolItems"
local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory")
local ls = Player:WaitForChild("leaderstats")
local HasGun = InvData:WaitForChild("HasGun")

local points = ls:WaitForChild("Points")
local exp = ls:WaitForChild("Experience")
local level = ls:WaitForChild("Level")

local DataToSave = {
    HasGun.Value,
    points.Value,
    exp.Value,
    level.Value,
}

InventoryItems:SetAsync(Key, DataToSave)
end)

spawn(function()

while wait(AUTOSAVE_INTERVAL) do

for i, Player in pairs (game:GetService("Players"):GetChildren()) do --for every player in the game, save
print("Auto-saving " .. Player.Name .. "'s Data")

local Key = "PlayerIdNum-"..Player.UserId.."_ToolItems"
local InvData = Player:WaitForChild("Backpack"):WaitForChild("Inventory")
local ls = Player:WaitForChild("leaderstats")
local HasGun = InvData:WaitForChild("HasGun")
local points = ls:WaitForChild("Points")
local exp = ls:WaitForChild("Experience")
local level = ls:WaitForChild("Level")

local DataToSave = {
    HasGun.Value,
    points.Value,
    exp.Value,
    level.Value,
}

InventoryItems:SetAsync(Key, DataToSave)
print("Successfully Auto-saved " .. Player.Name .. "'s Data")

end
end
end)

return module


2
Can you tab your code. User#5423 17 — 6y
0
Your module returns an empty table. Does anything 'require' this ModuleScript? If not, this script won't even run! Otherwise, it would be useful to know what output there is from this script (what does it print/not print?) chess123mate 5873 — 6y
0
Yes, before you use module scripts, learn how to use them. Also, how come now I see everyone using datastores using modulescripts? hiimgoodpack 2009 — 6y
1
Finally, someone who agrees that you should tab code. Theres even an auto tab feature, it is more difficult to delete tabs then to just leave them be. hiimgoodpack 2009 — 6y
View all comments (3 more)
0
Yes, there's a script descendant from the ModuleScript that tells it to require. Line 139 prints every two minutes, "Successfully Auto Saved". No error message is received. I'd done some removal in MSWord of some extra lines, thats why its not tabbed. I'll repaste it for you. EDIT: Done. Never2Humble 90 — 6y
0
Within ROBLOX my main use of ModuleScripts is to organise code so many of my modules don't return (much) at all to where they were required. Pejorem 164 — 6y
0
I did it as a ModuleScript because that's what I was told to do. :D But indention aside, which I went back and did above....why is my script not working? I don't receive any Output errors. That last Print line says it saved, but nothing is there once a player leaves the game and returns. I'm honestly at a loss. Never2Humble 90 — 6y

1 answer

Log in to vote
0
Answered by
Pejorem 164
6 years ago
Edited 6 years ago

It's awfully disturbing to read code without indentation and general lack of formality, but what you seek is usage of BindToClose() which simply tells the server to stay open up to 30 seconds for you to do whatever needs to be done when the last player in the server leaves it.

game:BindToClose(function()
    --the code that stalls the ending of the server goes here
end)
--personally I don't use this example but it's a start lol
local canCloseServer

game.Players.PlayerRemoving:Connect(function(plr)
    saveStats(plr)
    if game.Players.NumPlayers < 1 then canCloseServer = true end
end)

game:BindToClose(function()
    repeat wait(1) until canCloseServer
end)

http://wiki.roblox.com/index.php?title=API:Class/DataModel/BindToClose

0
Thanks for the response! :D Just to confirm, would I include this in its own Script inside ServerScriptService? Or do I work it around the PlayerRemoving portion of my DataStore module script? Never2Humble 90 — 6y
1
It's just an example so you can rework it how you like, check out my data store module. It's not fully developed and may look a bit daunting/confusing but hopefully it'll give you some ideas:https://www.roblox.com/library/989287701/Data-Handling-V0-5 Pejorem 164 — 6y
Ad

Answer this question