Need Help With Datastores

I’m trying to make a system where the player can buy things, like weapons, kill sounds, etc… The issue is, while I was trying to make a way to communicate between a server script and module script to trade the players item data (The data that holds all of the items that the player owns), It said that I could not submit a dictionary to a datastore.

104: Cannot store Dictionary in data store. Data stores can only accept valid UTF-8 characters. 

I’m not sure what else to do so that I can save the players owned items like Kill Sounds (Which are located in the Player’s Player Object) and Weapons (Which is located in the Store and there Backpack). Does anyone know anything else I can do as an alternative to this?

Here’s the scripts

ServerScript / Datastore Script

--\\ Datastores - Made By StarJ3M //--
local DataStoreService = game:GetService("DataStoreService") -- Datastore Service

local totalBricksData = DataStoreService:GetDataStore("totalBricks") -- The All-Time Bricks
local studData = DataStoreService:GetDataStore("studData") -- The Currency
local killSoundData = DataStoreService:GetDataStore("savedKillSound") -- The Kill Sound for the player

local playerItemData = DataStoreService:GetDataStore("playerItemData")

local shopItemData = DataStoreService:GetDataStore("shopItemData")

local shopOptionsRemote = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvents"):WaitForChild("LoadShopOptions")
local shopModule = require(game:GetService("ReplicatedStorage"):WaitForChild("ShopModule"))

--\\ Functions //--
game.Players.PlayerAdded:Connect(function(player)
	local killSound = Instance.new("Sound", player)
	killSound.Name = "killSound"
	killSound.Volume = 2
	killSound.SoundId = game:GetService("ReplicatedStorage"):WaitForChild("KillSounds"):WaitForChild("default").SoundId
	
	local items = shopModule.createOwnedData(player)
	
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"
	
	local Studs = Instance.new("NumberValue", leaderstats) -- The Currency
	Studs.Name = "Studs"
	Studs.Value = 0
	
	local Bricks = Instance.new("IntValue", leaderstats) -- The Bricks broken between matches
	Bricks.Name = "Bricks"
	Bricks.Value = 0
	
	local totalBricks = Instance.new("IntValue", leaderstats) -- All time bricks broken
	totalBricks.Name = "T. Bricks"
	totalBricks.Value = 0
	
	local brickData
	local studsData
	
	local itemsData
	local possibleKillSound
	
	local success, errorMessage = pcall(function()
		brickData = totalBricksData:GetAsync(player.UserId)
		studsData = studData:GetAsync(player.UserId)
		
		possibleKillSound = killSoundData:GetAsync(player.UserId)
		itemsData = playerItemData:GetAsync(player.UserId)
	end)
	
	if success then
		totalBricks.Value = brickData
		Studs.Value = studsData
		killSound.SoundId = possibleKillSound
		
		items = itemsData
	elseif errorMessage then
		warn(player.Name.."'s data cannot be found!..")
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local leaderstats = player.leaderstats
	
	totalBricksData:SetAsync(player.UserId, leaderstats["T. Bricks"].Value)
	studData:SetAsync(player.UserId, leaderstats.Studs.Value)
	killSoundData:SetAsync(player.UserId, player.killSound.SoundId)
	
	local playerItemTable
	
	for i, v in pairs(shopModule.listOfPlayerItemTables) do
		if v.ownerTag == player.Name then
			playerItemTable = v
		end
	end
	
	playerItemData:SetAsync(player.UserId, playerItemTable)
end)

--\\ Shop Functions //--
shopOptionsRemote.OnServerEvent:Connect(function(player, optionType)
	if optionType == "killSounds" then
		
		for index, option in pairs(player.PlayerGui:FindFirstChild("ShopGui"):FindFirstChild("ShopFrame"):WaitForChild("List"):GetDescendants()) do
			if option:IsA("ImageButton") then
				option:Destroy()
			end
		end
		
		for index, sound in pairs(shopModule.shopAssets.killSounds) do
			local shopOption = script:WaitForChild("ShopButton"):Clone()
			shopOption.Parent = player.PlayerGui:FindFirstChild("ShopGui"):FindFirstChild("ShopFrame"):WaitForChild("List")
			shopOption.Name = sound.Name
			shopOption.ViewportFrame.ViewportPart.BackFace.Texture = sound.Image
			shopOption.ViewportFrame.ViewportPart.FrontFace.Texture = sound.Image
			
			local id = Instance.new("StringValue")
			id.Name = "SoundId"
			id.Parent = shopOption
			id.Value = sound.ID
			
			local cost = Instance.new("IntValue")
			cost.Name = "Cost"
			cost.Parent = shopOption
			cost.Value = sound.Cost
		end
	end
end)

Shop Module / Module Script

local module = {}

local killSoundsFolder = game:GetService("ReplicatedStorage"):WaitForChild("KillSounds")

module.shopAssets = {
	killSounds = {
		Default = {
			Name = "default";
			ID = killSoundsFolder:WaitForChild("default").SoundId;
			Image = "rbxassetid://13431178414";
			Cost = 0;
		};

		Fart = {
			Name = "fart";
			ID = killSoundsFolder:WaitForChild("fart").SoundId;
			Image = "rbxassetid://13431188125";
			Cost = 1;
		};

		Bruh = {
			Name = "bruh";
			ID = killSoundsFolder:WaitForChild("Bruh").SoundId;
			Image = "rbxassetid://13431192434";
			Cost = 10;
		};

		TacoBell = {
			Name = "taco bell";
			ID = killSoundsFolder:WaitForChild("TacoBell").SoundId;
			Image = "rbxassetid://13431196956";
			Cost = 222;
		};

		YouDied = {
			Name = "you died";
			ID = killSoundsFolder:WaitForChild("You Died").SoundId;
			Image = "rbxassetid://13431200948";
			Cost = 6666;
		};

		Overdrive = {
			Name = "overdrive";
			ID = killSoundsFolder:WaitForChild("overdrive").SoundId;
			Image = "rbxassetid://13431206252";
			Cost = 7777;
		};

		Megamind = {
			Name = "mind mega";
			ID = killSoundsFolder:WaitForChild("mindmega").SoundId;
			Image = "rbxassetid://13431210474";
			Cost = 52010;
		};

		SteelSting = {
			Name = "steel sting";
			ID = killSoundsFolder:WaitForChild("steel sting").SoundId;
			Image = "rbxassetid://13431214322";
			Cost = 54321;
		};

		Augh = {
			Name = "auughhh";
			ID = killSoundsFolder:WaitForChild("auuugh").SoundId;
			Image = "rbxassetid://13431218141";
			Cost = 69000;
		};

		SuperMarioOnThePs4 = {
			Name = "mario on the ps4";
			ID = killSoundsFolder:WaitForChild("mario on the ps4").SoundId;
			Image = "rbxassetid://13431221878";
			Cost = 292013;
		};

		VineBoom = {
			Name = "vine boom";
			ID = killSoundsFolder:WaitForChild("vine boom").SoundId;
			Image = "rbxassetid://13431224975";
			Cost = 500000;
		};

		TragicEvents = {
			Name = "tragic events in history";
			ID = killSoundsFolder:WaitForChild("Tragic Events In History").SoundId;
			Image = "rbxassetid://13431238120";
			Cost = 1000000;
		};
	};
}

module.listOfPlayerItemTables = {}

function module.createOwnedData(player)
	local playerData = {
		ownerTag = player.Name; -- The owner of the data
		
		weapons = {
			classicBomb = {
				tool = game:GetService("ReplicatedStorage"):WaitForChild("Weapons"):WaitForChild("Classic Bomb");
			}
		};

		killSounds = {
			default = game:GetService("ReplicatedStorage"):WaitForChild("KillSounds"):WaitForChild("default");
		};
	}
	
	table.insert(module.listOfPlayerItemTables, playerData)
	
	return playerData
end

function module.adddToPlayerItemData(playerData, item)
	table.insert(playerData, item)
end

return module

You can use HttpService:JSONEncode to convert the dictionary to a string.

-- Services
local HttpsService = game:GetService("HttpsService")

-- Encode
local Encode = HttpsService:JSONEncode(playerItemTable)
playerItemData:SetAsync(player.UserId, Encode)

Note: You will have to use JSONDecode when you load the data back in.

local Decode = HttpsService:JSONDecode(playerItemData:GetAsync(player.UserId))
2 Likes

check to make sure the things in ur datastore arrays are only strings, numbers and booleans cuz datastore doesnt support roblox-only stuff like vector3s or ingame objects

Save it as a string.
game:GetService("ReplicatedStorage"):WaitForChild("Weapons"):WaitForChild("Classic Bomb").Name

that is probably ur error because roblox datastore does not store objects

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.