Hello everyone,
I’m currently working on a Roblox project where I need to store and retrieve a table of game data using DataStores.
Issue Description
I’m trying to save a table of game data to a DataStore and then load it to display the saved games in the game UI. The flow works as follows:
- A player inputs game details (Name, Description, IconId, ThumbnailId, GameId) and publishes the game.
- The game data is sent to the server, which saves it to a DataStore.
- The server then sends the updated game data to all clients.
- Clients receive the game data and clone a game template to display the game in the UI.
Problems Encountered
- Game Data Not Loading Properly: While I can see that the server successfully saves the game data, the client does not seem to properly receive and process this data.
-
Nil Game Data: The game template cloning function on the client side often encounters
nil
game data, causing errors.
ServerScriptService
local DataStoreService = game:GetService("DataStoreService")
local gamesDataStore = DataStoreService:GetDataStore("GamesData")
local games = {}
local function LoadGames()
local success, data = pcall(function()
return gamesDataStore:GetAsync("games")
end)
if success then
if data then
games = data
print("Games data loaded successfully.")
else
print("No games data found, initializing empty games table.")
games = {}
end
else
warn("Failed to load games data: " .. tostring(data))
games = {}
end
end
local function SaveGames()
local success, err = pcall(function()
gamesDataStore:SetAsync("games", games)
end)
if not success then
warn("Failed to save games data: " .. err)
end
end
LoadGames()
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PublishGameEvent = ReplicatedStorage:FindFirstChild("PublishGameEvent")
if not PublishGameEvent then
PublishGameEvent = Instance.new("RemoteEvent", ReplicatedStorage)
PublishGameEvent.Name = "PublishGameEvent"
end
local LoadGamesEvent = ReplicatedStorage:FindFirstChild("LoadGamesEvent")
if not LoadGamesEvent then
LoadGamesEvent = Instance.new("RemoteEvent", ReplicatedStorage)
LoadGamesEvent.Name = "LoadGamesEvent"
end
game.Players.PlayerAdded:Connect(function(player)
print("Player added, sending games data:", games)
LoadGamesEvent:FireClient(player, games)
end)
PublishGameEvent.OnServerEvent:Connect(function(player, gameData)
print("Received game data from client:", gameData)
table.insert(games, gameData)
SaveGames()
print("Game data saved successfully.")
PublishGameEvent:FireClient(player, true)
for _, plr in pairs(game.Players:GetPlayers()) do
LoadGamesEvent:FireClient(plr, games)
end
end)
Local Script inside ScreenGui
local function PublishGame()
local gameData = {
Name = AddGame.GameName.GameName.Text,
Description = AddGame.Description.Description.Text,
IconId = AddGame.IconID.IconID.Text,
ThumbnailId = AddGame.ThumbnailID.ThumbnailID.Text,
GameId = AddGame.GameID.GameID.Text,
Creator = game.Players.LocalPlayer.Name
}
print("Sending game data to server:", gameData)
if gameData.Name ~= "" and gameData.Description ~= "" and gameData.IconId ~= "" and gameData.ThumbnailId ~= "" and gameData.GameId ~= "" then
local success, errorMsg = pcall(function()
return MarketplaceService:PromptProductPurchase(player, productID)
end)
if success then
PublishGameEvent:FireServer(gameData)
MarketplaceService.PromptProductPurchaseFinished:Once(function(player, productId, wasPurchased)
if productId == productID and wasPurchased then
table.insert(games, gameData)
local gameTemplate = GameList.GameTemplate:Clone()
gameTemplate.NameText.Text = gameData.Name
gameTemplate.Icon.Image = "rbxassetid://" .. gameData.IconId
gameTemplate.Parent = GameList
gameTemplate.Visible = true
gameTemplate.PlayButton.MouseButton1Click:Connect(function()
TS:Teleport(gameData.GameId)
end)
gameTemplate.DescriptionButton.MouseButton1Click:Connect(function()
InformationFrame.Visible = true
InformationFrame.Position = UDim2.new(0, 0, 1, 0)
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local tween = TweenService:Create(InformationFrame, tweenInfo, { Position = UDim2.new(0, 0, 0, 0) })
tween:Play()
InformationFrame.Icon.Image = "rbxassetid://" .. gameData.IconId
InformationFrame.DescFrame.Description.Text = gameData.Description
InformationFrame.GameName.Text = gameData.Name
InformationFrame.Thumbnail.Image = "rbxassetid://" .. gameData.ThumbnailId
InformationFrame.Creator.Text = gameData.Creator
end)
end
end)
else
local errorMessage = errorMsg or "Unknown error"
warn("Publish failed: " .. errorMessage)
print("Error message:", errorMessage)
end
else
warn("Cannot publish: All fields are required.")
end
PublishGameEvent.OnClientEvent:Connect(function(success)
if success then
print("Game published successfully.")
AddGame.GameName.GameName.Text = ""
AddGame.Description.Description.Text = ""
AddGame.IconID.IconID.Text = ""
AddGame.ThumbnailID.ThumbnailID.Text = ""
AddGame.GameID.GameID.Text = ""
else
warn("Publish failed.")
end
end)
end
local function CloneGameTemplate(gameData)
local gameTemplate = GameList:FindFirstChild("GameTemplate")
if not gameTemplate then
warn("GameTemplate not found in GameList.")
return
end
gameTemplate = gameTemplate:Clone()
print("Cloning game template:")
print("gameData:", gameData)
if not gameData then
warn("gameData is nil.")
return
end
local nameText = gameTemplate:FindFirstChild("NameText")
local icon = gameTemplate:FindFirstChild("Icon")
local playButton = gameTemplate:FindFirstChild("PlayButton")
local descriptionButton = gameTemplate:FindFirstChild("DescriptionButton")
if not nameText then
warn("NameText not found in gameTemplate.")
else
nameText.Text = gameData.Name
end
if not icon then
warn("Icon not found in gameTemplate.")
else
icon.Image = "rbxassetid://" .. gameData.IconId
end
if not playButton then
warn("PlayButton not found in gameTemplate.")
else
playButton.MouseButton1Click:Connect(function()
TS:Teleport(gameData.GameId)
end)
end
if not descriptionButton then
warn("DescriptionButton not found in gameTemplate.")
else
descriptionButton.MouseButton1Click:Connect(function()
InformationFrame.Visible = true
InformationFrame.Position = UDim2.new(0, 0, 1, 0)
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local tween = TweenService:Create(InformationFrame, tweenInfo, { Position = UDim2.new(0, 0, 0, 0) })
tween:Play()
InformationFrame.Icon.Image = "rbxassetid://" .. gameData.IconId
InformationFrame.DescFrame.Description.Text = gameData.Description
InformationFrame.GameName.Text = gameData.Name
InformationFrame.Thumbnail.Image = "rbxassetid://" .. gameData.ThumbnailId
InformationFrame.Creator.Text = gameData.Creator
end)
end
gameTemplate.Parent = GameList
gameTemplate.Visible = true
end
local function LoadGames(games)
if not games then
warn("No games data received from server.")
return
end
print("Loading games:", games)
for _, gameData in pairs(games) do
print("Loading gameData:", gameData)
CloneGameTemplate(gameData)
end
end
LoadGamesEvent.OnClientEvent:Connect(function(games)
print("Received games data from server:", games)
LoadGames(games)
end)