Hi there! I’m brand new to coding and I’d like to see if anyone could give me some feedback on two of the really important parts in my code.
First is my datastore- So far I haven’t had any issues with it or noticed any dataloss, but I’m hoping that maybe someone with a lot of experience with datastores can look at it and verify that it actually looks 100% good or let me know if there’s perhaps some issue with it that may cause data loss eventually? Thank you!
local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")
local database = dataStoreService:GetDataStore("data")
local sessionData = {}
function playerAdded(player)
local Coins = Instance.new("IntValue")
Coins.Name = "Coins"
Coins.Parent = player
local Trails = {}
for i = 1, 24, 1 do
Trails[i] = Instance.new("BoolValue")
Trails[i].Name = "Trails" .. i
Trails[i].Parent = player
end
local success = nil
local playerData = nil
local attempt = 1
-----LOADS DATA OR ASSIGNS DEFAULT DATA-------
repeat
success, playerData = pcall(function()
return database:GetAsync(player.UserId)
end)
attempt += 1
if not success then
warn(playerData)
task.wait(3)
end
until success or attempt == 5
if success then
print("connected to database")
if not playerData then
playerData = {}
end
--checks player's data. If data is new it's given default value.
if playerData["Coins"] == nil then
playerData["Coins"] = 0
print("adding coins to player's data")
end
for i = 1, 24 do
if playerData["Trails" .. i] == nil then
playerData["Trails" .. i] = false
print("adding trail ".. i .. " to player's data")
end
end
sessionData[player.UserId] = playerData
else
warn("unable to get data for ", player.UserId)
player:Kick("Unable to load your data. Try again later.")
end
--checks for value changes and updates player data
Coins.Value = sessionData[player.UserId].Coins
Coins.Changed:Connect(function()
sessionData[player.UserId].Coins = Coins.Value
end)
for i = 1, 24 do
Trails[i].Value = sessionData[player.UserId]["Trails" .. i]
Trails[i].Changed:Connect(function()
sessionData[player.UserId]["Trails" .. i] = Trails[i].Value
end)
end
end
players.PlayerAdded:Connect(playerAdded)
function saveData(player)
if sessionData[player.UserId] then
local success = nil
local errorMsg = nil
local attempt = 1
repeat
success, errorMsg = pcall(function()
database:SetAsync(player.UserId, sessionData[player.UserId])
end)
attempt += 1
if not success then
warn(errorMsg)
task.wait(3)
end
until success or attempt == 5
if success then
print("Data saved for", player.Name)
else
warn("unable to save for ", player.Name)
end
end
end
players.PlayerRemoving:Connect(saveData)
function autoSave()
for _, player in pairs(game.Players:GetPlayers()) do
saveData(player)
end
end
game:BindToClose(function()
autoSave()
end)
while task.wait(300) do
autoSave()
end
and secondly is my code for handling the purchase of developer products. This also seems to be working as intended but I just want to run it by knowledgeable people just to double check. (“000000000” is just a placeholder, I do use the actual developer product IDs there)
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local productFunctions = {}
productFunctions[00000000] = function(receipt, player)
local jewels = player:WaitForChild("Jewels")
jewels.Value = jewels.Value + 100
return true
end
productFunctions[000000000] = function(receipt, player)
local jewels = player:WaitForChild("Jewels")
jewels.Value = jewels.Value + 300
return true
end
local function processReceipt(receiptInfo)
local userId = receiptInfo.PlayerId
local productId = receiptInfo.ProductId
print(userId, productId)
local player = Players:GetPlayerByUserId(userId)
if player then
local handler = productFunctions[productId]
local success, result = pcall(handler, receiptInfo, player)
if success then
return Enum.ProductPurchaseDecision.PurchaseGranted
else
warn("Failed to process receipt:", receiptInfo, result)
end
end
return Enum.ProductPurchaseDecision.NotProcessedYet
end
--when player buys something this fires
MarketplaceService.ProcessReceipt = processReceipt