Hello developers, I am making a tower defense game but there seems to be data errors everywhere. I dont know what is causing this and dont know how to fix it. There are data errors for the leaderstats XP/coins and there are data errors for selected towers in the GAME MATCH which is the teleported server where the actual tower defense game starts. Here is the first part of the data errors starting in the lobby game:
And here is the script for the ShopServer which buys towers from a gui:
ShopServer script in lobby server:
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local database = DataStoreService:GetDataStore("database7")
local towers = require(ReplicatedStorage:WaitForChild("TowerShop"))
local MAX_SELECTED_TOWERS = 5
local updateCurrencyEvent = ReplicatedStorage:WaitForChild("UpdateCurrency")
local data = {}
-- Load the players data
local function LoadData(player)
local success = nil
local playerData = nil
local attempt = 1
repeat
success, playerData = pcall(function()
return database:GetAsync(player.UserId)
end)
attempt += 1
if not success then
warn(playerData)
task.wait()
end
until success or attempt == 3
if success then
print("Connection success")
if not playerData then
print("New player, giving default data")
playerData = {
["Stars"] = 100,
["SelectedTowers"] = {"Pz. II"},
["OwnedTowers"] = {"Pz. II", "M2 Light"}
}
end
data[player.UserId] = playerData
updateCurrencyEvent:FireClient(player, playerData.Stars)
else
warn("Unable to get data for player", player.UserId)
player:Kick("There was a problem getting your data")
end
end
Players.PlayerAdded:Connect(LoadData)
-- Save the players data
local function SaveData(player)
if data[player.UserId] then
local success = nil
local playerData = nil
local attempt = 1
repeat
success, playerData = pcall(function()
return database:UpdateAsync(player.UserId, function()
return data[player.UserId]
end)
end)
attempt += 1
if not success then
warn(playerData)
task.wait()
end
until success or attempt == 3
if success then
print("Data saved successfully")
else
warn("Unable to save data for", player.UserId)
end
else
warn("No session data for", player.UserId)
end
end
Players.PlayerRemoving:Connect(function(player)
SaveData(player)
data[player.UserId] = nil
end)
game:BindToClose(function()
if not RunService:IsStudio() then
for index, player in pairs(Players:GetPlayers()) do
task.spawn(function()
SaveData(player)
end)
end
else
print("Shutting down inside studio")
end
end)
local function getItemStatus(player, itemName)
local playerData = data[player.UserId]
if table.find(playerData.SelectedTowers, itemName) then
return "Equipped"
elseif table.find(playerData.OwnedTowers, itemName) then
return "Owned"
else
return "For Sale"
end
end
local function updatePlayerLoadout(player)
local playerData = data[player.UserId]
if playerData then
local loadout = {}
for i = 1, MAX_SELECTED_TOWERS do
loadout[i] = playerData.SelectedTowers[i] or ""
end
ReplicatedStorage.UpdateLoadout:FireClient(player, loadout)
end
end
local function updatePlayerData(player, itemName, action)
local playerData = data[player.UserId]
if action == "For Sale" then
playerData.Stars -= towers[itemName].Price
table.insert(playerData.OwnedTowers, itemName)
elseif action == "Owned" then
table.insert(playerData.SelectedTowers, itemName)
if #playerData.SelectedTowers > MAX_SELECTED_TOWERS then
table.remove(playerData.SelectedTowers, 1)
end
elseif action == "Equipped" then
if #playerData.SelectedTowers > 1 then
local towerToRemove = table.find(playerData.SelectedTowers, itemName)
table.remove(playerData.SelectedTowers, towerToRemove)
end
end
updatePlayerLoadout(player)
updateCurrencyEvent:FireClient(player, playerData.Stars)
end
local function updatePlayerLoadout(player)
local playerData = data[player.UserId]
if playerData then
local loadout = {}
for i = 1, MAX_SELECTED_TOWERS do
loadout[i] = playerData.SelectedTowers[i] or ""
end
ReplicatedStorage.UpdateLoadout:FireClient(player, loadout)
end
end
local function updatePlayerData(player, itemName, action)
local playerData = data[player.UserId]
if action == "For Sale" then
playerData.Stars -= towers[itemName].Price
table.insert(playerData.OwnedTowers, itemName)
elseif action == "Owned" then
table.insert(playerData.SelectedTowers, itemName)
if #playerData.SelectedTowers > MAX_SELECTED_TOWERS then
table.remove(playerData.SelectedTowers, 1)
end
elseif action == "Equipped" then
if #playerData.SelectedTowers > 1 then
local towerToRemove = table.find(playerData.SelectedTowers, itemName)
table.remove(playerData.SelectedTowers, towerToRemove)
end
end
updatePlayerLoadout(player)
updateCurrencyEvent:FireClient(player, playerData.Stars)
end
local function updatePlayerLoadout(player)
local playerData = data[player.UserId]
if playerData then
local loadout = {}
for i = 1, MAX_SELECTED_TOWERS do
-- THIS PART HAS ERROR
loadout[i] = playerData.SelectedTowers[i] or ""
--THIS PART HAS ERROR
end
ReplicatedStorage.UpdateLoadout:FireClient(player, loadout)
end
end
local function updatePlayerData(player, itemName, action)
local playerData = data[player.UserId]
if action == "For Sale" then
playerData.Stars -= towers[itemName].Price
table.insert(playerData.OwnedTowers, itemName)
elseif action == "Owned" then
table.insert(playerData.SelectedTowers, itemName)
if #playerData.SelectedTowers > MAX_SELECTED_TOWERS then
table.remove(playerData.SelectedTowers, 1)
end
elseif action == "Equipped" then
if #playerData.SelectedTowers > 1 then
local towerToRemove = table.find(playerData.SelectedTowers, itemName)
table.remove(playerData.SelectedTowers, towerToRemove)
end
end
updatePlayerLoadout(player)
updateCurrencyEvent:FireClient(player, playerData.Stars)
end
ReplicatedStorage.InteractItem.OnServerInvoke = function(player, itemName)
local shopItem = towers[itemName]
local playerData = data[player.UserId]
if shopItem and playerData then
local status = getItemStatus(player, itemName)
if status == "For Sale" and shopItem.Price <= playerData.Stars then
updatePlayerData(player, itemName, "For Sale")
elseif status == "Owned" then
updatePlayerData(player, itemName, "Owned")
elseif status == "Equipped" then
updatePlayerData(player, itemName, "Equipped")
end
return playerData
else
warn("Tower/player data does not exist")
end
return false
end
ReplicatedStorage.GetData.OnServerInvoke = function(player)
return data[player.UserId]
end
Players.PlayerAdded:Connect(function(player)
LoadData(player)
updatePlayerLoadout(player)
end)
Here are the data errors I am getting in the GAME MATCH:
And here is the dataStore script:
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local database = DataStoreService:GetDataStore("database7")
local functions = ReplicatedStorage:WaitForChild("Functions")
-- tut
local getLoadoutFunction = functions:WaitForChild("GetLoadout")
-- tut
local getDataFunc = functions:WaitForChild("GetData")
local events = ReplicatedStorage:WaitForChild("Events")
local exitEvent = events:WaitForChild("ExitGame")
local MAX_SELECTED_TOWERS = 5
local data = {}
-- Load the players data
local function LoadData(player)
local success = nil
local playerData = nil
local attempt = 2
repeat
success, playerData = pcall(function()
return database:GetAsync(player.UserId)
end)
attempt += 1
if not success then
warn(playerData)
task.wait()
end
until success or attempt == 3
if success then
print("Connection success")
if not playerData then
print("New player, giving default data")
playerData = {
["Stars"] = 200,
["SelectedTowers"] = {"Pz. II"},
["OwnedTowers"] = {"Pz. II", "M2 Light"}
}
end
-- tut
data[player.UserId] = playerData
local stya = Instance.new("NumberValue",player)
stya.Value = data[player.UserId].Stars
stya.Name = "CombatXP"
-- THIS IS THE PART WITH THE ERROR
for i, tower in pairs(data[player.UserId].SelectedTowers) do
-- THIS IS THE PART WITH THE ERROR
local tower = ReplicatedStorage.Towers:FindFirstChild(tower)
if tower then
Instance.new("StringValue",player.SelectedTower).Name = tower.Name
end
end
-- tut
else
warn("Unable to get data for player", player.UserId)
player:Kick("There was a problem getting your data")
end
end
Players.PlayerAdded:Connect(LoadData)
-- Save the players data
local function SaveData(player)
if data[player.UserId] then
local success = nil
local playerData = nil
local attempt = 1
local info = workspace.Info
local Stars = math.round(info.Wave.Value)
if info.Message.Value == "VICTORY" and info.Mode.Value == "PettyWarfare" then
Stars = 60
elseif info.Message.Value == "VICTORY" and info.Mode.Value == "Normal" then
Stars = 80
elseif info.Message.Value == "VICTORY" and info.Mode.Value == "WorldWar" then
Stars = 120
end
if info.Message.Value == "GAME OVER" and info.Mode.Value == "PettyWarfare" then
Stars = 30
end
if info.Message.Value == "GAME OVER" and info.Mode.Value == "Normal" then
Stars = 45
end
if info.Message.Value == "GAME OVER" and info.Mode.Value == "WorldWar" then
Stars = 60
end
data[player.UserId].Stars += Stars
repeat
success, playerData = pcall(function()
return database:UpdateAsync(player.UserId, function()
return data[player.UserId]
end)
end)
attempt += 1
if not success then
warn(playerData)
task.wait()
end
until success or attempt == 3
if success then
print("Data saved successfully")
else
warn("Unable to save data for", player.UserId)
end
else
warn("No session data for", player.UserId)
end
end
exitEvent.OnServerEvent:Connect(function(player)
SaveData(player)
data[player.UserId] = nil
end)
game:BindToClose(function()
if not RunService:IsStudio() then
for index, player in pairs(Players:GetPlayers()) do
task.spawn(function()
SaveData(player)
end)
end
else
print("Shutting down inside studio")
end
end)
getDataFunc.OnServerInvoke = function(player)
return data[player.UserId]
end
If you are still reading this message I am very thankful for you trying to help me and I will be very very very thankful if you help me with this data error because I have been trying to solve this for weeks without any fixes