--// Services \\--
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local DataStoreService = game:GetService("DataStoreService")
--// Variables \\--
local dataStore = DataStoreService:GetDataStore("TestData")
--// Modules \\--
local Modules = ReplicatedStorage:FindFirstChild("Modules")
local ParticleEffects = require(Modules.ParticleEffects)
--// Objects to clone \\--
local objectsToClone = ReplicatedStorage:FindFirstChild("ObjectsToClone")
local levelUpSFX = objectsToClone:FindFirstChild("LevelUpSFX")
local levelUpParticle = objectsToClone:FindFirstChild("LevelUpReference").Attachment
--// Functions \\--
-- Budget checking for retries
local function waitForRequestBudget(requestType)
local currentBudget = DataStoreService:GetRequestBudgetForRequestType(requestType)
while currentBudget < 3 do
currentBudget = DataStoreService:GetRequestBudgetForRequestType(requestType)
task.wait(5)
end
end
-- Sets up player data
local function setUp(player)
local userId = player.UserId
local key = "Player_" .. userId
player:SetAttribute("isVip", false)
player:SetAttribute("currentPowerUp", "None")
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
local points = Instance.new("NumberValue")
points.Name = "Points"
local coins = Instance.new("NumberValue")
coins.Name = "Coins"
local level = Instance.new("NumberValue")
level.Name = "Level"
local exp = Instance.new("NumberValue")
exp.Name = "Exp"
local success, returnValue
repeat
waitForRequestBudget(Enum.DataStoreRequestType.GetAsync)
success, returnValue = pcall(dataStore.GetAsync, dataStore, key)
until success or not Players:FindFirstChild(player.Name)
if success then
if returnValue == nil then
returnValue = {
Points = 0,
Coins = 20,
Level = 1,
Exp = 0,
}
end
points.Value = returnValue["Points"] or 0
coins.Value = returnValue["Coins"] or 20
level.Value = returnValue["Level"] or 1
exp.Value = returnValue["Exp"] or 0
points.Parent = leaderstats
coins.Parent = leaderstats
level.Parent = leaderstats
exp.Parent = leaderstats
leaderstats.Parent = player
exp:GetPropertyChangedSignal("Value"):Connect(function()
if exp.Value >= level.Value * 100 then
local character = player.Character
local HumanoidRootPart = character:FindFirstChild("HumanoidRootPart")
local levelUpParticleClone = levelUpParticle:Clone()
local levelUpSFXClone = levelUpSFX:Clone()
exp.Value -= level.Value * 100
level.Value += 1
levelUpParticleClone.Parent = HumanoidRootPart
levelUpSFXClone.Parent = HumanoidRootPart
levelUpSFXClone:Play()
levelUpSFXClone.Ended:Connect(function()
levelUpSFXClone:Destroy()
levelUpSFXClone = nil
end)
ParticleEffects.EmitParticles(levelUpParticleClone, character)
end
end)
else
print("Error loading "..player.Name.."'s data!")
end
end
-- Saving player data
local function save(player, dontWait)
local userId = player.UserId
local key = "Player_" .. userId
local leaderstats = player:FindFirstChild("leaderstats")
if leaderstats then
local pointValue = leaderstats.Points.Value
local coinValue = leaderstats.Coins.Value
local levelValue = leaderstats.Level.Value
local expValue = leaderstats.Exp.Value
local dataTable = {
Points = pointValue,
Coins = coinValue,
Level = levelValue,
Exp = expValue,
}
local success, returnValue
repeat
if not dontWait then
waitForRequestBudget(Enum.DataStoreRequestType.SetIncrementAsync)
end
success, returnValue = pcall(dataStore.UpdateAsync, dataStore, key, function()
return dataTable
end)
until success
if success then
print(player.Name.."'s data has been saved!")
else
print("There was an error saving "..player.Name.."'s data!")
end
end
end
-- Handling saving for players already in game
for _, player in ipairs(Players:GetPlayers()) do
coroutine.wrap(setUp)(player)
end
-- Delays the game from shutting down by X seconds so the PlayerRemoving Event will 100% fire
local function onShutdown()
if RunService:IsStudio() then
task.wait(2)
else
local finished = Instance.new("BindableEvent")
local allPlayers = Players:GetPlayers()
local leftPlayers = #allPlayers
for _, player in ipairs(allPlayers) do
coroutine.wrap(function()
save(player)
leftPlayers -= 1
if leftPlayers == 0 then
finished:Fire()
end
end)()
end
finished.Event:Wait()
end
end
Players.PlayerAdded:Connect(setUp)
Players.PlayerRemoving:Connect(save)
game:BindToClose(onShutdown)
--// Autosaving every 5 minutes
while true do
task.wait(300)
for _, player in ipairs(Players:GetPlayers()) do
coroutine.wrap(save)(player)
end
end
Hello I’m currently working on a DataStore and I followed a DataStore Tutorial and changed it to my needs. However, I want to implement a way to warn the player if the data hasn’t loaded completely and also implement a method to kick the player if data hasn’t loaded but I’m unsure of where to place it?
Datastores are something that I have difficulties with and I can’t think of a way to reciprocate datastores failing to test if my methods would work. In addition, is there anything I would need to improve for this datastore? I noticed when players leave a moment after it autosave, queues begin to throttle. All help is appreciated!
Thank you!