I am working on a cash doors system similar to those found in simulator games, where a player earns a certain amount of a currency in order to purchase access to an area behind a door. I have implemented the code below as the main script for the system:
local openGui = game.ReplicatedStorage:WaitForChild("OpenDoor1Gui")
local door = game.Workspace:WaitForChild("Zone1Door")
local purchaseGui = game.StarterGui.Door1PurchaseGUI.Frame
local event = game.ReplicatedStorage:WaitForChild("RemoveDoor1")
local DataStoreService = game:GetService("DataStoreService")
local DoorsUnlocked = DataStoreService:GetDataStore("DoorsUnlocked")
local DoorData = {}
game.Players.PlayerAdded:Connect(function(player)
DoorData[player] = DoorsUnlocked:GetAsync(player.UserId)
if not DoorData[player] then
DoorData[player] = {}
DoorsUnlocked:SetAsync(player.UserId, DoorData[player])
end
end)
game.Players.PlayerRemoving:Connect(function(player)
DoorsUnlocked:SetAsync(player.UserId, DoorData[player])
DoorData[player] = nil
end)
door.Touched:Connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player or not player:IsA("Player") then return end
local tokens = player.leaderstats.Tokens
if tokens.Value >= 3000 then
openGui:FireClient(player)
end
end)
event.OnServerEvent:Connect(function(player)
local tokens = player.leaderstats.Tokens
tokens.Value -= 3000
end)
If a player were to leave the game and rejoin, the doors they’ve purchased should stay unlocked. I am using a table Datastore and RemoteEvents to destroy the door such as “RemoveDoor1” in order to do so. How would I complete the system in order to do so?
I would highly recommend you to use pcalls. If you dont know what that is let me explain: When you try to reach Roblox servers sometimes it glitches and doesnt reach the servers. So if you dont use pcalls for Datastores when it glitches it may delete all the players data.
game.Players.PlayerAdded:Connect(function(player)
local Success, ErrorMessage = pcall(function()
DoorData[player] = DoorsUnlocked:GetAsync(player.UserId)
if not DoorData[player] then
DoorData[player] = {}
DoorsUnlocked:SetAsync(player.UserId, DoorData[player])
end
end)
end)
Your idea to use pcall() is sound, but there is no point of declaring Success and ErrorMessage variables but not using them to handle errors. Ideally, the pcall would wrap just the GetAsync, and then your normal code would be in an if Success then block afterwards, and you’d have error handling code in the else block that logs the error, potentially sets up a retry, and then ultimately notifies the player if all retries fail that their session is borked and will probably not track their progress.
If each door can only be unlocked one after another, you could just store the door that was unlocked the most recently. A more adaptable solution would be to store a unique identifier (name, id, etc.) for each door in an array.
I attempted to add table arrays in order to save the data. The data seems to save fine, but the RemoteEvent was never fired. What did I do wrong?
local openGui = game.ReplicatedStorage:WaitForChild("OpenDoor1Gui")
local door = game.Workspace:WaitForChild("Zone1Door")
local purchaseGui = game.StarterGui.Door1PurchaseGUI.Frame
local event = game.ReplicatedStorage:WaitForChild("RemoveDoor1")
local DataStoreService = game:GetService("DataStoreService")
local DoorsUnlocked = DataStoreService:GetDataStore("DoorsUnlocked")
local DoorData = {}
game.Players.PlayerAdded:Connect(function(player)
DoorData[player] = DoorsUnlocked:GetAsync(player.UserId)
warn("Door Data Loaded!")
if not DoorData[player] then
DoorData[player] = {0, 0}
DoorsUnlocked:SetAsync(player.UserId, DoorData[player])
warn("New Data Created!")
end
if DoorData[1] == 1 then
event:FireClient(player)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
DoorsUnlocked:SetAsync(player.UserId, DoorData[player])
DoorData[player] = nil
warn("Door Data Saved!")
end)
door.Touched:Connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player or not player:IsA("Player") then return end
local tokens = player.leaderstats.Tokens
if tokens.Value >= 3000 then
openGui:FireClient(player)
end
end)
event.OnServerEvent:Connect(function(player)
local tokens = player.leaderstats.Tokens
tokens.Value -= 3000
DoorData[1] = 1
end)
How would I properly initialize the table to {0, 0} and change it to {1, 0} when the player buys the first door? Each index should correspond to another door.
The initializing part turned out to just be a testing error. The code below doesn’t affect the player’s DoorData. Is this the correct way to modify a table?