Need help with Storing DataStore in my Sol's RNG-like roblox experience (it does not save rn)

Hello there, it sure has been a long time since I have asked peoples in the devforum for help fix my roblox studio scripts, I will make it kinda quick because my head is not feeling good after using Roblox Studio’s in-built AI script helper and ChatGPT’s Script support for more then hours straight and still not getting an correct fixes…

  1. What do you want to achieve? - I want this long lines of script that I took some notes from This youtube video for me to make an Roblox Experience inspired by another roblox experience called “Sol’s RNG”, I used a bunch of AI script code helps from in-built from studio and chat gpt pretty much a lot…

  2. What is the issue? - the problem is that when player joins the game and makes an progresses in the experience (such as rolling for Auras such as Goog, Rare and such), the game script in the ServerScriptService wouldn’t load back the Data of player whenever they rejoin… I do not know how can I fix this issue yet… but here is the LUA script code of it and the rbxm game file in case you do want to view what is wrong…

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

local RollEvent = ReplicatedStorage:WaitForChild("RollEvent")
local Chances = require(ReplicatedStorage:WaitForChild("Chances"))
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")

local Inventory = {}

-- Function to save player data to DataStore
local function SavePlayerData(User)
	local userId = User.UserId
	local success, err = pcall(function()
		local rolls = User:FindFirstChild("leaderstats"):FindFirstChild("Rolls").Value
		local saveData = {Inventory = Inventory[userId], Rolls = rolls}
		-- Update the existing data in the DataStore instead of overwriting it
		local existingData = playerDataStore:GetAsync("PlayerData"..userId) or {}
		for key, value in pairs(saveData) do
			existingData[key] = value
		end
		playerDataStore:SetAsync("PlayerData"..userId, existingData)
	end)
	if not success then
		warn("Failed to save data for player "..userId..": "..err)
	end
end

-- Function to handle player join
local function PlayerJoined(User)
	-- Step 1: Create the leaderstats folder and parent it to the User
	local LeaderStats = Instance.new("Folder", User)
	LeaderStats.Name = "leaderstats"

	-- Step 2: Create the Rolls IntValue inside the leaderstats folder
	local Rolls = Instance.new("IntValue", LeaderStats)
	Rolls.Name = "Rolls"

	-- Attempt to load the player's data
	local userId = User.UserId
	local success, data = pcall(function()
		return playerDataStore:GetAsync("PlayerData"..userId)
	end)

	-- Handle the retrieved or default data
	if success then
		if data then
			Inventory[userId] = data.Inventory or {
				Limit = 10,
				LatestRoll = nil,
				Equipped = nil,
				Backpack = {}
			}
			-- Load the Rolls value
			local rollsValue = data.Rolls or 0
			Rolls.Value = rollsValue
		else
			Inventory[userId] = {
				Limit = 10,
				LatestRoll = nil,
				Equipped = nil,
				Backpack = {}
			}
			Rolls.Value = 0 -- Default Rolls value if no data is found
		end
	else
		-- Log an error if data retrieval failed
		warn("Failed to load data for player "..userId)
	end
end

-- Function to handle player leaving
local function PlayerLeft(User)
	SavePlayerData(User)
end

-- Connect events
Players.PlayerAdded:Connect(PlayerJoined)
Players.PlayerRemoving:Connect(PlayerLeft)

local SelectRNG = require(ReplicatedStorage:WaitForChild("SelectRNG"))

RollEvent.OnServerInvoke = function(User, Header)
	local UserInventory = Inventory[User.UserId]
	local UserLimit = UserInventory["Limit"]
	local Backpack = UserInventory["Backpack"]

	if Header == "Get" then
		if #Backpack >= UserLimit then
			table.remove(Backpack, table.find(Backpack, UserInventory["Equipped"]) or UserLimit)
		end
		table.insert(Backpack, UserInventory["LastestRoll"])

	elseif Header == "Waste" then
		UserInventory["LastestRoll"] = nil
	elseif Header == "GetInventory" then
		return Backpack
	else
		local Result = Chances[SelectRNG(User)][1]
		UserInventory["LastestRoll"] = Result
		return Result
	end
	print(Backpack)
	return
end

SolsRNGLikeGameTest1.rbxl (72.2 KB)

  1. What solutions have you tried so far? - I have used Roblox Studio’s In-Built AI Script Advice/Explain code system and ChatGPT website in the attempt of solving that issue, but things did not go well…

So please let me know whenever you found the issue or want to discuss this Topic About, my eyesight is kind of blurry from scripting for hours straight, I will go take a rest now :slightly_frowning_face:

1 Like

You could try using ProfileService. There’s a tutorial on YouTube by VectorThree

1 Like

hello there, I have fixed my script to also adapt the ProfileServices, but there is this specific line of script code that has issues, the problematic line of script is this…

’’’lua
local ProfileService = require(game.ServerScriptService.ProfileService) —unknown global…
’’’

I am still not sure how could I fix this line of code does not know what global ProfileService is… but let me know if you could help me with this🥹

1 Like

That’s because ProfileService is a library / asset. You need to manually insert it inside your game in order to use it.

Here, you can get the asset. Once you did so, you need to open the Toolbox inside Studio and go over to the section My Models, and click on the asset you just bought (for free).

2 Likes

Hello there, I have tried my best to add the ProfileService Script (from This ProfileService Script in studio marketplace ) inside ServerScriptService and used multiple ChatGPT AI script code generations ( Link to my attempt of generating AI code for save Inventory and Rolls with ProfileService System ) to make the Fixed version of script so the game will save the new datas of Inventory and Rolls IntValues correctly, but there has not been any single time that the script has functioned properly :sob:

most of the times it showed this specific errors and warns like this on in-game output…:

DataStoreService: CantStoreValue: Cannot store Dictionary in data store. Data stores can only accept valid UTF-8 characters. API: UpdateAsync, Data Store: PlayerDataStore” (Error)
[ProfileService]: DataStore API error [Store:“PlayerDataStore”;Key:“1015911803”] - “104: Cannot store Dictionary in data store. Data stores can only accept valid UTF-8 characters.”” (Warn)

I still have no absolute idea how I can fix this but I will show you this script codes in below incase if you do want to help fixing this script, this new version of the script has mutated much from generating with AI Script generators…

-- new Script inside ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local ProfileService = require(game.ServerScriptService.ProfileService) -- Assuming ProfileService is in ServerScriptService

local RollEvent = ReplicatedStorage:WaitForChild("RollEvent")
local Chances = require(ReplicatedStorage:WaitForChild("Chances"))
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")

local Inventory = {}

-- ProfileService Setup
local profileStore = ProfileService.GetProfileStore(
	"PlayerDataStore", 
	{
		DataStore = playerDataStore,
		OnProfileLoad = function(profile)
			-- Initialize default values if profile data is empty
			profile.Data.Inventory = profile.Data.Inventory or {
				Limit = 10,
				LatestRoll = nil,
				Equipped = nil,
				Backpack = {}
			}
			profile.Data.Rolls = profile.Data.Rolls or 0
		end
	}
)

-- Function to serialize a Lua table into a string
local function SerializeTable(table)
	local json = game:GetService("HttpService"):JSONEncode(table)
	return json
end

-- Function to deserialize a string into a Lua table
local function DeserializeTable(json)
	local table = game:GetService("HttpService"):JSONDecode(json)
	return table
end

-- Function to save player data
local function SavePlayerData(profile)
	local encodedInventory = SerializeTable(Inventory[profile.UserId])
	profile.Data.Inventory = encodedInventory
	profile:Save()
end

local function PlayerJoined(User)
	local profile = profileStore:LoadProfileAsync(tostring(User.UserId), "ForceLoad")
	if profile then
		profile:Reconcile()
		-- Deserialize inventory data when loading the profile
		Inventory[User.UserId] = DeserializeTable(profile.Data.Inventory)
	else
		warn("Failed to load profile for player "..tostring(User.UserId))
	end
end

local function PlayerLeft(User)
	local profile = profileStore:LoadProfileAsync(tostring(User.UserId))
	if profile then
		SavePlayerData(profile)
		profile:Release()
	end
end

-- Connect events
Players.PlayerAdded:Connect(PlayerJoined)
Players.PlayerRemoving:Connect(PlayerLeft)

local SelectRNG = require(ReplicatedStorage:WaitForChild("SelectRNG"))

RollEvent.OnServerInvoke = function(User, Header)
	local profile = profileStore:LoadProfileAsync(tostring(User.UserId))
	if profile then
		local UserInventory = DeserializeTable(profile.Data.Inventory)
		local UserLimit = UserInventory["Limit"]
		local Backpack = UserInventory["Backpack"]

		if Header == "Get" then
			if #Backpack >= UserLimit then
				table.remove(Backpack, table.find(Backpack, UserInventory["Equipped"]) or UserLimit)
			end
			table.insert(Backpack, UserInventory["LastestRoll"])

		elseif Header == "Waste" then
			UserInventory["LastestRoll"] = nil
		elseif Header == "GetInventory" then
			return Backpack
		else
			local Result = Chances[SelectRNG(User)][1]
			UserInventory["LastestRoll"] = Result
			return Result
		end
		print(Backpack)
	end
	if profile then profile:Release() end
	return
end

```lua
--Old Script inside ServerScriptService which does not uses an ProfileService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local RollEvent = ReplicatedStorage:WaitForChild("RollEvent")
local Chances = require(ReplicatedStorage:WaitForChild("Chances"))
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")

local Inventory = {}

-- Function to save player data to DataStore
local function SavePlayerData(User)
	local userId = User.UserId
	local success, err = pcall(function()
		local rolls = User:FindFirstChild("leaderstats"):FindFirstChild("Rolls").Value
		local saveData = {Inventory = Inventory[userId], Rolls = rolls}
		-- Update the existing data in the DataStore instead of overwriting it
		local existingData = playerDataStore:GetAsync("PlayerData"..userId) or {}
		for key, value in pairs(saveData) do
			existingData[key] = value
		end
		playerDataStore:SetAsync("PlayerData"..userId, existingData)
	end)
	if not success then
		warn("Failed to save data for player "..userId..": "..err)
	end
end

-- Function to handle player join
local function PlayerJoined(User)
	-- Step 1: Create the leaderstats folder and parent it to the User
	local LeaderStats = Instance.new("Folder", User)
	LeaderStats.Name = "leaderstats"

	-- Step 2: Create the Rolls IntValue inside the leaderstats folder
	local Rolls = Instance.new("IntValue", LeaderStats)
	Rolls.Name = "Rolls"

	-- Attempt to load the player's data
	local userId = User.UserId
	local success, data = pcall(function()
		return playerDataStore:GetAsync("PlayerData"..userId)
	end)

	-- Handle the retrieved or default data
	if success then
		if data then
			Inventory[userId] = data.Inventory or {
				Limit = 10,
				LatestRoll = nil,
				Equipped = nil,
				Backpack = {}
			}
			-- Load the Rolls value
			local rollsValue = data.Rolls or 0
			Rolls.Value = rollsValue
		else
			Inventory[userId] = {
				Limit = 10,
				LatestRoll = nil,
				Equipped = nil,
				Backpack = {}
			}
			Rolls.Value = 0 -- Default Rolls value if no data is found
		end
	else
		-- Log an error if data retrieval failed
		warn("Failed to load data for player "..userId)
	end
end

-- Function to handle player leaving
local function PlayerLeft(User)
	SavePlayerData(User)
end

-- Connect events
Players.PlayerAdded:Connect(PlayerJoined)
Players.PlayerRemoving:Connect(PlayerLeft)

local SelectRNG = require(ReplicatedStorage:WaitForChild("SelectRNG"))

RollEvent.OnServerInvoke = function(User, Header)
	local UserInventory = Inventory[User.UserId]
	local UserLimit = UserInventory["Limit"]
	local Backpack = UserInventory["Backpack"]

	if Header == "Get" then
		if #Backpack >= UserLimit then
			table.remove(Backpack, table.find(Backpack, UserInventory["Equipped"]) or UserLimit)
		end
		table.insert(Backpack, UserInventory["LastestRoll"])

	elseif Header == "Waste" then
		UserInventory["LastestRoll"] = nil
	elseif Header == "GetInventory" then
		return Backpack
	else
		local Result = Chances[SelectRNG(User)][1]
		UserInventory["LastestRoll"] = Result
		return Result
	end
	print(Backpack)
	return
end

thank you so much for reading my replies :face_holding_back_tears:

1 Like

hello? is anyone able to help me with Fixing this script for make an game similar to Sol’s RNG? I am having an problem with datastore that when player makes progresses on the game and left and rejoin and made another progresses, new progress would not save :sob:

hey there, why no one else is responding to me…? I am facing big problems with my script after i added ProfileService system to my script but no one is here to help me fix this issue… :face_holding_back_tears:

hello there, I have made an new topic post on the scripting support which I made it for find some helps for fix the script I have posted in here, but no one has replying to me… ;-;
here is the link to that Forum topic post … let me know whenever you are able to help me :face_holding_back_tears: