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

Datastore's SetAsync not working?

Asked by
Rhidlor 42
6 years ago

The SetAsync in question here is on line 49, the print statement above it fires but the one below does not. I've been cracking away at this for hours, recruiting the help of people on Discord to no avail. If anyone could assist me with this I would be greatly indebted to you.

local Data = game:GetService("DataStoreService"):GetDataStore("Data")

game.Players.PlayerAdded:Connect(function(Player)
    print("Key " .. Player.UserId)
    createCanSave(Player)
    local Success, Result = pcall(getPlayerData, Player)
    if Success then
        print(Result)
        print(Result.Stats.Exp)
        if Result and Result.Stats.Level > 0 then
            print("Got Result")
            setStats(Player, Result.Stats)
            setBackpack(Player, Result.Backpack)
        else
            print("Didnt get Result")
            defaultStats(Player)
            game.ReplicatedStorage.Weapons.StarterSword:Clone().Parent = Player:WaitForChild("Backpack")
        end
    else
        print("Error: " .. Result)
    end
end)

game.Players.PlayerRemoving:Connect(function(Player)
    print("Key " .. Player.UserId)
    if Player.CanSave.Value then
        print(Player.Name .. " is saving")
        local DataDictionary = {
            Stats = getStats(Player),
            Backpack = getBackpack(Player)
        }
        local Success, Result = pcall(setPlayerData, Player, DataDictionary)
        if Success then
            print("Successfully saved " .. Player.Name)
        else
            print("Error while saving " .. Player.Name .. " Message: " .. Result)
        end
    else
        print(Player.Name .. " can't save")
    end
end)

function getPlayerData(Player)
    return Data:GetAsync(tostring(Player.UserId))
end

function setPlayerData(Player, DataDictionary)
    print("Began SetAsync")
    Data:SetAsync(tostring(Player.UserId), DataDictionary)
    print("Ended SetAsync")
end

function createCanSave(Player)
    local CanSave = Instance.new("BoolValue", Player)
    CanSave.Name = "CanSave"
    CanSave.Value = true
end

--Stats Portion

function setStats(Player, SavedStats)
    local Stats = createStats(Player)
    if SavedStats then
        print("Got SavedStats")
        Stats.Level.Value = SavedStats.Level
        Stats.Exp.Value = SavedStats.Exp
        Stats.Gold.Value = SavedStats.Gold
    end
end

function defaultStats(Player)
    print("Defaulting stats for " .. Player.Name)
    local Stats = createStats(Player)
    Stats.Level.Value = 1
    Stats.Exp.Value = 0
    Stats.Gold.Value = 25
end

function createStats(Player)
    local Stats = Instance.new("Folder", Player)
    Stats.Name = "Stats"

    local Level = Instance.new("IntValue", Stats)
    Level.Name = "Level"    

    local Exp = Instance.new("IntValue", Stats)
    Exp.Name = "Exp"

    local Gold = Instance.new("IntValue", Stats)
    Gold.Name = "Gold"

    return Stats
end

function getStats(Player)
    local PlayerStats = {}
    if Player:FindFirstChild("Stats") then
        for _, Stat in pairs(Player.Stats:GetChildren()) do
            print("Saving " .. Player.Name .. "'s " .. Stat.Name .. " = " .. Stat.Value)
            PlayerStats[Stat.Name] = Stat.Value
        end
    end
    print("returning PlayerStats")
    return PlayerStats
end

--Backpack Portion

function setBackpack(Player, SavedWeapons)
    if SavedWeapons then
        print("Got SavedWeapons")
        for _, WeaponName in pairs(SavedWeapons) do
            print("Weapon for loop")
            local Weapon = game.ReplicatedStorage.Weapons:FindFirstChild(WeaponName)
            if Weapon then
                print("Loading " .. Weapon.Name)
                Weapon:Clone().Parent = Player:WaitForChild("Backpack")
                Weapon:Clone().Parent = Player:WaitForChild("StarterGear")
            end
        end
    else
        print("SavedWeapons else fired")
    end 
end

function getBackpack(Player)
    local WeaponsTable = {}
    local EquippedWeapon = getEquippedWeapon(Player)
    if EquippedWeapon then
        print("Saving " .. Player.Name .. "'s " .. EquippedWeapon.Name)
        table.insert(WeaponsTable, EquippedWeapon.Name)
    end
    for _, Weapon in pairs(Player.Backpack:GetChildren()) do
        print("Saving " .. Player.Name .. "'s " .. Weapon.Name)
        table.insert(WeaponsTable, Weapon.Name)
    end
    print("returning WeaponsTable")
    return WeaponsTable
end

function getEquippedWeapon(Player)
    local Character = game.Workspace:FindFirstChild(Player.Name)
    if Character then
        for _, Item in pairs(Character:GetChildren()) do
            if Item:IsA("Tool") then
                return Item
            end
        end 
    end
    return
end

1 answer

Log in to vote
0
Answered by 6 years ago

The game closed

When the game is closing, any scripts which yield (Which happens with SetAsync) do not get resumed. As such, you'll need to register a quick yield on close with BindToClose

0
Thank you so much, is there a way I can have SetAsync in game.Players.PlayerRemoving and game:BindToClose without throttling? Rhidlor 42 — 6y
Ad

Answer this question