Struggling to detect saved data correctly in a local script

My code is supposed to accomplish the following:

  1. On join, a value (x, named “Door Opened”) is assigned to the player, with a value of 0. This is meant to represent the # of doors they have opened. (Server Script “SaveDoors”)
  2. A server script (“keyDetector1”) for each door handles the detection of a key, and fires to a local script (“openDoor1”) which opens the door if the check goes through. Door opening is meant to be local. Once the door is opened, the value is increased by 1.
  3. The first script saves the value through a DataStore once the player leaves. This value is then fetched upon joining, the value is detected, and it fires to a different local script (“openDoorsOnJoin”) which is supposed to open “unlocked” doors that were previously opened by that specific player.

My issue is the save data seems to be saving and updating for all players. While teamtesting, if I have a value of “3”, and the doors are open for me, upon the other players joining, their values are also 3, and the doors are open for them as well. The values, doors, and save data should all be local. The issue seems to be with sending a value to the client when loading unlocked doors.

Because building this script was an amalgamation of help from different sources, as I’m fairly new to scripting, I can’t seem to find help for this specific issue… assuming that it’s only one issue, that being the value transferring correctly.

I have tried assigning x’s value (x.Value) to a variable such as “xValue” and sending that on FireClient,
as well as sending the variable “data” which is fetched on player join from the DataStore and equal to x.Value instead.

I’m making these variables in general because, on the local script which is supposed to open those “unlocked” doors on join, the player’s saved value is already there. But when I attempt to fetch that variable (local x = player:FindFirstChild(“Opened Doors”)) in the local script, and get the value that way, it does not work.

As of now, there are no errors in the output, the code just isn’t doing what I intend.

Code for the save data script (“SaveDoors”)

local DSS = game:GetService("DataStoreService")
local DS = DSS:GetDataStore("DoorsOpened")
local Players = game:GetService("Players")
local RemoteEvent = game.ReplicatedStorage.OpenDoors.DoorsOpenedOnJoin

local function waitForRequestBudget(requestType)
	local currentBudget = DSS:GetRequestBudgetForRequestType(requestType)
	while currentBudget < 1 do
		currentBudget = DSS:GetRequestBudgetForRequestType(requestType)
		wait(5)
	end
end

local function setUp(player)
	local userId = player.UserId
	local key = "Player_" .. userId
	
	local x = Instance.new("IntValue")
	x.Name = "Doors Opened"
	x.Value = 0
	local userId = player.UserId
	local key = "Player_" .. userId

	local data = DS:GetAsync(key)

	x.Value = data or 0
	x.Parent = player
	
	if data == 1 then
		local value = 1
		RemoteEvent:FireClient(player, value)
	end
	if data == 2 then
		local value = 2
		RemoteEvent:FireClient(player, value)
	end
	if data == 3 then
		local value = 3
		RemoteEvent:FireClient(player, value)
	end
	
	local success, ret
	repeat
		waitForRequestBudget(Enum.DataStoreRequestType.GetAsync)
		success, ret= pcall(DS.GetAsync, DS, key)
	until success or not player
	
	if success then
		x.Value = ret or 0
		
		x.Parent = player
	end
end

local function save(player)
	local userId = player.userId
	local key = "Player_" .. userId
	local x = player:FindFirstChild("Doors Opened")
	
	if x then
		local xValue = x.Value
		local success, ret
		repeat
			waitForRequestBudget(Enum.DataStoreRequestType.SetIncrementAsync)
			success, ret= pcall(DS.SetAsync, DS, key, xValue)
		until success
	end
end

local function onShutdown()
	wait(1)
end

game:BindToClose(onShutdown)
game.Players.PlayerAdded:Connect(setUp)
game.Players.PlayerRemoving:Connect(save)

Code for opening the door on touch (“keyDetector1”)

local Door1 = game.Workspace.Doors.Door1
local RemoteEvent = game.ReplicatedStorage.OpenDoors.DoorOpen1
local itemName = "Key1"
local Players = game:GetService("Players")

Door1.Keyhole1.Touched:Connect(function(hit)
	local model = hit:FindFirstAncestorWhichIsA("Model")
	if not model then return end

	local player = game.Players:GetPlayerFromCharacter(model)
	if not player then return end
	if hit.Parent.Name == "Key1" and hit.BrickColor == Door1.Keyhole1.BrickColor then
		if player.Backpack:FindFirstChild(itemName) and player.Backpack[itemName]:IsA("Tool") then
			player.Backpack.Key1:Destroy()
		end
		if player.Character and player.Character:FindFirstChild(itemName) and player.Character[itemName]:IsA("Tool") then
			player.Character[itemName]:Destroy()
		end
		RemoteEvent:FireClient(player)
		
		local x = player:FindFirstChild("Doors Opened")
		if x then
			if x.Value == 0 then
				x.Value += 1
				local xValue = x.Value
				print("Updated value: [" .. xValue .. "]")
			end
		end
	end
end)

Local script which opens the door after being fired from keyDetector1 (“openDoor1”)

local RemoteEvent = game.ReplicatedStorage.OpenDoors.DoorOpen1

RemoteEvent.OnClientEvent:Connect(function(player)
	local Door1 = game.Workspace.Doors.Door1
	local Keyhole1 = game.Workspace.Doors.Door1.Keyhole1
	local Key1 = game.Workspace.Keys.Key1

	Door1:Destroy()
	Keyhole1:Destroy()
	Key1:Destroy()
	print("Door opened")
end)

And finally, local script for opening unlocked doors on join. (“openDoorsOnJoin”)

local RemoteEvent = game.ReplicatedStorage.OpenDoors.DoorsOpenedOnJoin

local function openDoor1()
	local Keyhole1 = game.Workspace.Doors.Door1.Keyhole1
	local Key1 = game.Workspace.Keys.Key1
	local Door1 = game.Workspace.Doors.Door1

	Door1:Destroy()
	Keyhole1:Destroy()
	Key1:Destroy()
	print("Door 1 opened")
end

local function openDoor2()
	local Keyhole2 = game.Workspace.Doors.Door2.Keyhole2
	local Key2 = game.Workspace.Keys.Key2
	local Door2 = game.Workspace.Doors.Door2

	Door2:Destroy()
	Keyhole2:Destroy()
	Key2:Destroy()
	print("Door 2 opened")
end

local function openDoor3()
	local Keyhole3 = game.Workspace.Doors.Door3.Keyhole3
	local Key3 = game.Workspace.Keys.Key3
	local Door3 = game.Workspace.Doors.Door3

	Door3:Destroy()
	Keyhole3:Destroy()
	Key3:Destroy()
	print("Door 3 opened")
end

RemoteEvent.OnClientEvent:Connect(function(player, value)	
	if value == 1 then
		openDoor1()
	end
	if value == 2 then
		openDoor1()
		openDoor2()
	end
	if value == 3 then
		openDoor1()
		openDoor2()
		openDoor3()
	end
end)

This most likely isn’t the solution, but when connecting to an OnClientEvent, you don’t need to pass the player, as you know what player is receiving the data. This means that data is coming back nil and the player value when connecting is the data.

Did some tweaking of my own to fix up the script, but your suggestion was indeed the culprit! Thanks!