Why is my photo saving not working?

You can write your topic however you want, but you need to answer these questions:

  1. **What do you want to achieve? I want to make the photos the player takes save.

  2. **What is the issue? The photos aren’t persisting across sessions.

  3. **What solutions have you tried so far? I tried a lot of things, but I can’t seem to get it to work.

It is printing the data, but, i think the issue is to do with the localscript, or it retrieving the data from the severscrpt.
my local script (photo taker thing)

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local Debris = game:GetService("Debris")
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera

-- Get the necessary GUI elements
local gui = player:WaitForChild("PlayerGui"):WaitForChild("Camera")
local photoFrame = gui:WaitForChild("PhotoFrame")
local viewport = photoFrame:WaitForChild("ViewportFrame")
local photoAlbum = gui:WaitForChild("PhotoAlbum")
local photoList = photoAlbum:WaitForChild("Photos")
local uiGridLayout = photoList:WaitForChild("UIGridLayout")  -- Using UIGridLayout instead of UIListLayout
local cameranoise = game.StarterPlayer.StarterCharacterScripts.click
-- Position PhotoAlbum in the center
photoAlbum.Size = UDim2.new(.8, 0, .8, 0)  -- Adjust the size as needed
photoAlbum.Position = UDim2.new(0.5, 0, 0.5, 0)  -- Center the frame on screen
photoAlbum.AnchorPoint = Vector2.new(0.5, 0.5)  -- Set the anchor point to the center
photoAlbum.BackgroundColor3 = Color3.fromRGB(30, 30, 30)  -- Background color
photoAlbum.BackgroundTransparency = 0.2
photoAlbum.BorderSizePixel = 0
photoAlbum.Visible = false  -- Initially hidden

-- Set UIGridLayout for grid arrangement
uiGridLayout.CellSize = UDim2.new(0, 130, 0, 130)  -- Size of each photo
uiGridLayout.FillDirection = Enum.FillDirection.Horizontal  -- Arrange items horizontally
uiGridLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center  -- Center the items horizontally
uiGridLayout.VerticalAlignment = Enum.VerticalAlignment.Top  -- Align the items at the top vertically

-- Function to update the canvas size for scrolling

local function updateCanvasSize()
	local photoCount = #photoList:GetChildren()  -- Get the number of photos
	local columnCount = math.floor(photoList.AbsoluteSize.X / uiGridLayout.CellSize.X.Offset)  -- How many columns can fit horizontally
	local rowCount = math.ceil(photoCount / columnCount)  -- Calculate rows based on the number of photos and columns

	-- Add some space at the bottom to prevent clipping of the last row
	local extraPadding = 10  -- Adjust the padding value as necessary

	-- Update canvas size based on rows, with added extra padding
	local newCanvasSize = UDim2.new(0, 0, 0, rowCount * uiGridLayout.CellSize.Y.Offset + extraPadding)  -- Adjust canvas height based on rows
	photoList.CanvasSize = newCanvasSize
end


local function addFakeSkybox(viewport, camPos)
	-- Skybox images (you'll need to set these to the correct sky textures)
	local skyboxImages = {
		Front = "rbxassetid://6444884337", -- Replace with actual skybox image IDs
		Back = "rbxassetid://6444884337",
		Left = "rbxassetid://6444884337",
		Right = "rbxassetid://6444884337",
		Up = "rbxassetid://6412503613",
		Down = ""
	}

	-- Function to create a face of the skybox
	local function makeFace(imageId, position, rotation)
		local part = Instance.new("Part")
		part.Size = Vector3.new(500, 500, 1)
		part.Anchored = true
		part.CanCollide = false
		part.Transparency = 1
		part.CFrame = CFrame.new(camPos + position) * rotation
		part.Parent = viewport

		local surfaceGui = Instance.new("SurfaceGui")
		surfaceGui.Face = Enum.NormalId.Front
		surfaceGui.AlwaysOnTop = true
		surfaceGui.LightInfluence = 0
		surfaceGui.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud
		surfaceGui.PixelsPerStud = 50
		surfaceGui.Adornee = part
		surfaceGui.Parent = part

		local image = Instance.new("ImageLabel")
		image.Size = UDim2.fromScale(1, 1)
		image.Image = imageId
		image.BackgroundTransparency = 1
		image.BorderSizePixel = 0
		image.Parent = surfaceGui
	end

	local dist = 300 -- Distance from camera for the skybox faces

	-- Create skybox faces with different orientations
	makeFace(skyboxImages.Front, Vector3.new(0, 0, -dist), CFrame.Angles(0, math.pi, 0))
	makeFace(skyboxImages.Back, Vector3.new(0, 0, dist), CFrame.new())
	makeFace(skyboxImages.Left, Vector3.new(-dist, 0, 0), CFrame.Angles(0, math.pi / 2, 0))
	makeFace(skyboxImages.Right, Vector3.new(dist, 0, 0), CFrame.Angles(0, -math.pi / 2, 0))
	makeFace(skyboxImages.Up, Vector3.new(0, dist, 0), CFrame.Angles(math.pi / 2, 0, 0))
	makeFace(skyboxImages.Down, Vector3.new(0, -dist, 0), CFrame.Angles(-math.pi / 2, 0, 0))
end

local function takePhoto()
	print("Taking photo...")  
	photoFrame.Visible = true

	-- Create a new camera for the viewport
	local camClone = Instance.new("Camera")
	camClone.CFrame = camera.CFrame * CFrame.new(0, 0, -2)  -- Slightly move it back
	viewport.CurrentCamera = camClone



	-- Clear old clones in the viewport
	for _, child in ipairs(viewport:GetChildren()) do
		if child:IsA("BasePart") then
			child:Destroy()
		end
	end

	-- Add fake skybox to viewport
	addFakeSkybox(viewport, camClone.CFrame.Position)

	-- Clone visible BaseParts (excluding terrain)
	for _, obj in ipairs(workspace:GetDescendants()) do
		if obj:IsA("BasePart") and obj.Transparency < 1 and not obj:IsDescendantOf(workspace.Terrain) then
			local success, clone = pcall(function() return obj:Clone() end)
			if success then
				clone.Anchored = true
				clone.Parent = viewport
			else
				print("Failed to clone object: " .. obj.Name)
			end
		end
	end

	-- Simulate flash
	local flash = Instance.new("Frame")
	flash.Size = UDim2.fromScale(1, 1)
	flash.BackgroundColor3 = Color3.new(1, 1, 1)
	flash.BackgroundTransparency = 0
	flash.ZIndex = 10
	flash.Parent = gui
	TweenService:Create(flash, TweenInfo.new(0.3), {BackgroundTransparency = 1}):Play()
	Debris:AddItem(flash, 0.5)

	-- Save to album
	local photoClone = photoFrame:Clone()
	photoClone.Visible = true
	photoClone.Size = UDim2.new(0, 130, 0, 130)
	photoClone:ClearAllChildren()

	local newViewport = Instance.new("ViewportFrame")
	newViewport.Size = UDim2.fromScale(1, 1)
	newViewport.BackgroundTransparency = 1
	newViewport.CurrentCamera = camClone
	newViewport.Parent = photoClone

	-- Clone parts into new viewport
	for _, obj in ipairs(viewport:GetChildren()) do
		if obj:IsA("BasePart") then
			local partClone = obj:Clone()
			partClone.Anchored = true
			partClone.Parent = newViewport
		end
	end

	photoClone.Parent = photoList
	updateCanvasSize()
	wait(1)
	print("Photo taken and added to album.")
end
--load

local function loadSavedPhotos()
	local savedData = game.ReplicatedStorage:WaitForChild("GetSavedPhotos"):InvokeServer()

	-- Print the entire savedData to understand its structure
	print("Saved Data: ", savedData)

	-- Check if savedData is valid
	if not savedData or #savedData == 0 then
		print("No saved photos found.")
		return
	end

	-- Iterate through the savedData to load each photo
	for _, photo in ipairs(savedData) do
		print("Loaded photo data: ", photo)  -- Debugging the structure of each photo
		local cfComponents = photo.cf
		local cf = CFrame.new(unpack(cfComponents))  -- Recreate the CFrame from the saved components

		print("Loaded CFrame: ", cf)  -- Debug the CFrame

		-- Create a camera and set its position to the saved CFrame
		local camClone = Instance.new("Camera")
		camClone.CFrame = cf
		-- Continue your photo creation logic...
	end

	-- If no data is printed here, check the structure of savedData on the server-side
	print("Loaded", #savedData, "saved photos.")
	updateCanvasSize()  -- Update the UI to account for the new photos
end
 game.Players.PlayerAdded:Connect(function()
		task.wait(1)
	loadSavedPhotos()
 end)





and my server script (saver thing)

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local photoStore = DataStoreService:GetDataStore("PhotoAlbumStore")
local savePhotoEvent = ReplicatedStorage:WaitForChild("SavePhotoEvent")

-- Save a new photo when client sends it
savePhotoEvent.OnServerEvent:Connect(function(player, camCFrame)

	local userId = tostring(player.UserId)
	local success, currentData = pcall(function()
		return photoStore:GetAsync(userId)
	end)
	if not success then
		warn("Failed to load photo data for", player.Name)
		currentData = {}
	end

	currentData = currentData or {}
	table.insert(currentData, {cf = {camCFrame:components()}})

	local saveSuccess, err = pcall(function()
		photoStore:SetAsync(userId, currentData)
	end)
	if not saveSuccess then
		warn("Failed to save photo for", player.Name, err)
	else
		print("Saved photo for", player.Name)
	end

end)


-- ✅ ADD THIS PART BELOW
local getSavedPhotos = ReplicatedStorage.GetSavedPhotos


getSavedPhotos.OnServerInvoke = function(player)
	print("step1")
	local userId = tostring(player.UserId)
	local success, data = pcall(function()
		return photoStore:GetAsync(userId)
	end)
	if success and data then
		print("step2")
		return data
		
	else
		warn("Could not load saved photos for", player.Name)
		return {}
	end
end
-- ✅ END OF ADDED PART

-- Optional: Load on join and do something
Players.PlayerAdded:Connect(function(player)
	local userId = tostring(player.UserId)
	local success, data = pcall(function()
		return photoStore:GetAsync(userId)
	end)
	if success and data then
		-- Can be sent to client for display
		print("Loaded photo data for", player.Name, data)
	else
		warn("Could not load photo data", player.Name)
	end
end)

any suggestions or fixes on why its not working?