local K=game:GetService("\068\097\116\097\083\116\111\114\101\083\101\114\118\105\099\101")local N=K:GetDataStore("\083\068\076")local y=game:GetService("\080\108\097\121\101\114\115")local l=game:GetService("\083\101\114\118\101\114\083\116\111\114\097\103\101")local L=Instance.new("\070\111\108\100\101\114")L.Name="\083\068\076"L.Parent=l local J=true local U=Instance.new("\066\105\110\100\097\098\108\101\070\117\110\099\116\105\111\110")U.Name="\065\100\100\084\114\097\099\107\101\100\086\097\108\117\101"U.Parent=L local T={}U.OnInvoke=function(K,N,y)if J then if string.sub(N,-5)=="\086\097\108\117\101"then if K==nil then return false,"\078\097\109\101 \109\117\115\116 \098\101 \112\114\111\118\105\100\101\100\046"end if N==nil then return false,"\084\121\112\101 \109\117\115\116 \098\101 \112\114\111\118\105\100\101\100\046"end if y==nil then return false,"\068\101\102\097\117\108\116 \118\097\108\117\101 \109\117\115\116 \098\101 \112\114\111\118\105\100\101\100\046"end table.insert(T,{K;N;y})return true else return false,"\073\110\118\097\108\105\100 \116\121\112\101\046 \077\117\115\116 \098\101 \097 \086\097\108\117\101 \116\121\112\101\046"end else return false,"\067\097\110 \110\111\116 \097\100\100 \110\101\119 \116\114\097\099\107\101\100 \118\097\108\117\101 \097\102\116\101\114 \105\110\105\116\105\097\108\105\122\097\116\105\111\110 \105\115 \099\111\109\112\108\101\116\101\046 \083\101\110\100 \097 \114\101\113\117\101\115\116 \101\097\114\108\105\101\114\046"end end y.PlayerAdded:Connect(function(K)J=false local y=Instance.new("\070\111\108\100\101\114")y.Name="\083\068\076"y.Parent=K for K,N in pairs(T)do local l=Instance.new(N[2])l.Name=N[1]l.Parent=y l.Value=N[3]end local l,L=pcall(function()local l=N:GetAsync(K.UserId)if not l then l={}end for K,N in pairs(T)do if l[N[1]]then(y:FindFirstChild(N[1])).Value=l[N[1]]end end end)if not l then K:Kick("\070\097\105\108\101\100 \116\111 \108\111\097\100 \100\097\116\097\046 \080\108\101\097\115\101 \114\101\106\111\105\110\046")warn(L)end end)y.PlayerRemoving:Connect(function(K)local y=K.UserId local l=K:FindFirstChild("\083\068\076")if l then local L={}for K,N in pairs(T)do L[N[1]]=(l:FindFirstChild(N[1])).Value end local J,U=pcall(function()N:SetAsync(K.UserId,L)end)if not J then warn(U)print("\082\101\116\114\121\105\110\103\046\046\046")J,U=pcall(function()N:SetAsync(y,L)end)if J then print("\083\117\099\099\101\115\115\033")else print("\070\097\105\108\101\100 \116\111 \115\097\118\101 \100\097\116\097 \102\111\114 \112\108\097\121\101\114 "..(K.Name..(" \040"..(K.UserId.."\041"))))warn(U)end end end end)
-- Get the DataStoreService and create a new DataStore called "SDL"
local service = game:GetService("DataStoreService")
local dataStore = service:GetDataStore("SDL")

-- Get the Players service
local players = game:GetService("Players")

-- Create a new folder in ServerStorage to hold the SDL values
local serverStorage = game:GetService("ServerStorage")
local serverFolder = Instance.new("Folder")
serverFolder.Name = "SDL"
serverFolder.Parent = serverStorage

-- Set up a RemoteFunction to allow server scripts to add tracked values
local acceptingValues = true
local addTrackedValue = Instance.new("BindableFunction")
addTrackedValue.Name = "AddTrackedValue"
addTrackedValue.Parent = serverFolder

-- Create an empty table to hold the tracked values
local trackedValues = {}

-- Set up the OnServerInvoke function for the RemoteFunction
addTrackedValue.OnInvoke = function(name, type, defaultValue)
    -- Only accept new values before initialization is complete
    if acceptingValues then
        -- Check that the type is a Value type
        if string.sub(type, -5) == "Value" then
            -- Check that all required parameters are provided
            if name == nil then
                return false, "Name must be provided."
            end
            if type == nil then
                return false, "Type must be provided."
            end
            if defaultValue == nil then
                return false, "Default value must be provided."
            end
            -- Add the new tracked value to the table
            table.insert(trackedValues, {name, type, defaultValue})
            return true
        else
            return false, "Invalid type. Must be a Value type."
        end
    else
        return false, "Can not add new tracked value after initialization is complete. Send a request earlier."
    end
end

-- Set up a PlayerAdded event to initialize SDL values for new players
players.PlayerAdded:Connect(function(player)
    -- Stop accepting new values
    acceptingValues = false
    -- Create a new folder in the player to hold their SDL values
    local playerFolder = Instance.new("Folder")
    playerFolder.Name = "SDL"
    playerFolder.Parent = player
    -- Loop through the tracked values and create new instances for each one
    for _, value in pairs(trackedValues) do
        local newValue = Instance.new(value[2])
        newValue.Name = value[1]
        newValue.Parent = playerFolder
        newValue.Value = value[3]
    end
    -- Try to load the player's data from the DataStore
    local success, errormessage = pcall(function()
        local data = dataStore:GetAsync(player.UserId)
        -- Ensure that the data is not nil
        if not data then
            data = {}
        end
        -- Loop through the tracked values and set their values to the loaded data
        for _, value in pairs(trackedValues) do
            if data[value[1]] then
                playerFolder:FindFirstChild(value[1]).Value = data[value[1]]
            end
        end
    end)
    -- If loading the data fails, kick the player and print an error message
    if not success then
        player:Kick("Failed to load data. Please rejoin.")
        warn(errormessage)
    end
end)

-- Set up a PlayerRemoving event to save SDL values for leaving players
players.PlayerRemoving:Connect(function(player)
    --Access the player's ID
    local playerID = player.UserId
    -- Find the player's SDL folder
    local playerFolder = player:FindFirstChild("SDL")
    if playerFolder then
        -- Create a table to hold the player's data
        local data = {}
        -- Loop through the tracked values and add their values to the data table
        for _, value in pairs(trackedValues) do
            data[value[1]] = playerFolder:FindFirstChild(value[1]).Value
        end
        -- Try to save the data to the DataStore
        local success, errormessage = pcall(function()
            dataStore:SetAsync(player.UserId, data)
        end)
        -- If saving the data fails, print an error message and retry once
        if not success then
            warn(errormessage)
            print("Retrying...")
            success, errormessage = pcall(function()
                dataStore:SetAsync(playerID, data)
            end)
            -- If the retry succeeds, print a success message
            if success then
                print("Success!")
            else
                -- If the retry fails, print an error message
                print("Failed to save data for player " .. player.Name .. " (" .. player.UserId .. ")")
                warn(errormessage)
            end
        end
    end
end)