Script Location : ServerScriptService Script Type : ModuleScript
-- My scripter and I have been stuck on it for hours, help would be nice! We have no idea why it doesn't work! --
-- Setup table that we will return to scripts that require the ModuleScript.
local PlayerStatManager = {}
-- Create variable for the DataStore.
local DataStoreService = game:GetService('DataStoreService')
local Events = workspace:WaitForChild("Events", 30)
local playerData = DataStoreService:GetDataStore('PlayerData')
-- Create variable to configure how often the game autosaves the player data.
local AUTOSAVE_INTERVAL = 30
-- Number of times we can retry accessing a DataStore before we give up and create
-- an error.
local DATASTORE_RETRIES = 3
-- Table to hold all of the player information for the current session.
local sessionData = {}
-- Function the other scripts in our game can call to change a player's stats. This
-- function is stored in the returned table so external scripts can use it.
function PlayerStatManager:ChangeStat(player, statName, changeValue)
sessionData[player][statName] = changeValue
end
function UpdateData(player)
local playerleaderstats = player:WaitForChild("leaderstats", 30)
local playerWins = playerleaderstats:WaitForChild("Wins", 30)
local playerLevel = playerleaderstats:WaitForChild("Level", 30)
local playerCoins = playerleaderstats:WaitForChild("Coins", 30)
local playerBoughtItems = player:WaitForChild("BoughtItems", 30)
local playerTimesVisited = player:WaitForChild("TimesVisited", 30)
local boughtitemst = {}
for i, v in pairs(playerBoughtItems:GetChildren()) do
boughtitemst[i] = v.Name
end
sessionData[player] = {
Wins = playerWins.Value,
Level = playerLevel.Value,
Coins = playerCoins.Value,
BoughtItems = boughtitemst,
TimesVisited = playerTimesVisited.Value
}
end
-- Function to retry the passed in function several times. If the passed in function
-- is unable to be run then this function returns false and creates an error.
local function dataStoreRetry(dataStoreFunction)
local tries = 0
local success = true
local data = nil
repeat
tries = tries + 1
success = pcall(function() data = dataStoreFunction() end)
if not success then wait(1) end
until tries == DATASTORE_RETRIES or success
if not success then
warn('Could not access DataStore! Warn players that their data might not get saved!')
end
return success, data
end
-- Function to retrieve player's data from the DataStore.
local function getPlayerData(player)
Events:WaitForChild("DataIconEvent", 30):FireClient(player, "In Progress", "Getting progress...", true)
return dataStoreRetry(function()
Events:WaitForChild("DataIconEvent", 30):FireClient(player, "Success", "Progress loaded!", true)
return playerData:GetAsync(player.UserId)
end)
end
-- Function to save player's data to the DataStore.
local function savePlayerData(player)
if sessionData[player] then
Events:WaitForChild("DataIconEvent", 30):FireClient(player, "In Progress", "Saving progress...", false)
return dataStoreRetry(function()
Events:WaitForChild("DataIconEvent", 30):FireClient(player, "Success", "Progress saved!", false)
print("Saved")
return playerData:SetAsync(player.UserId, sessionData[player])
end)
end
end
-- Function to add player to the sessionData table. First check if the player has
-- data in the DataStore. If so, we'll use that. If not, we'll add the player to
-- the DataStore.
local function setupPlayerData(player)
local success, data = getPlayerData(player)
if not success then
-- Could not access DataStore, set session data for player to false.
sessionData[player] = false
Events:WaitForChild("DataIconEvent", 30):FireClient(player, "Fail", "Something went wrong...", true)
else
if not data then
-- DataStores are working, but no data for this player
sessionData[player] = {
Wins = 0,
Level = 1,
Coins = 10,
BoughtItems = {},
TimesVisited = 1
}
savePlayerData(player)
else
-- DataStores are working and we got data for this player
sessionData[player] = data
local playerleaderstats = player:WaitForChild("leaderstats", 30)
local playerWins = playerleaderstats:WaitForChild("Wins", 30)
local playerLevel = playerleaderstats:WaitForChild("Level", 30)
local playerLvlUpExp = playerLevel:WaitForChild("LvlUpExp", 30)
local playerCoins = playerleaderstats:WaitForChild("Coins", 30)
local playerBoughtItems = player:WaitForChild("BoughtItems", 30)
local playerTimesVisited = player:WaitForChild("TimesVisited", 30)
local CoinsMultiplier = player:WaitForChild("CoinsMultiplier", 30)
local ExpMultiplier = player:WaitForChild("ExpMultiplier", 30)
playerWins.Value = sessionData[player].Wins
playerLevel.Value = sessionData[player].Level
playerLvlUpExp.Value = ((playerLevel.Value * 3) / ExpMultiplier.Value)
playerCoins.Value = sessionData[player].Coins
for i, v in pairs(sessionData[player].BoughtItems) do
local boughtitem = Instance.new("BoolValue", playerBoughtItems)
boughtitem.Name = v
boughtitem.Value = true
end
playerTimesVisited.Value = sessionData[player].TimesVisited
end
end
end
-- Function to run in the background to periodically save player's data.
local function autosave()
while wait(AUTOSAVE_INTERVAL) do
for player, data in pairs(sessionData) do
--UpdateData(player)
savePlayerData(player)
print("Autosaving...")
end
end
end
-- Bind setupPlayerData to PlayerAdded to call it when player joins.
game.Players.PlayerAdded:connect(setupPlayerData)
-- Call savePlayerData on PlayerRemoving to save player data when they leave.
-- Also delete the player from the sessionData, as the player isn't in-game anymore.
game.Players.PlayerRemoving:connect(function(player)
--UpdateData(player)
savePlayerData(player)
sessionData[player] = nil
end)
-- Start running autosave function in the background.
spawn(autosave)
-- Return the PlayerStatManager table to external scripts can access it.
return PlayerStatManager
If you do end up fixing it my scripter and I will add you in credits! Thanks!
