Tips on how I can change the player's Data?

So I have obtained the player’s Data from line 43 by activeData = GetDataRemoteFunction:InvokeServer(), which prints out the player’s Data after putting a print statement a line below.

What I want to be able to do at this point is to change specifically the number of how much the player has of a particular resource. This is inside of a tool activated function, to further elaborate we’re collecting ‘resources’ as a player in this little game demo of mine.

How can I change the player’s Data using the instance “activeData” which I used as I explained earlier to get the player’s data?

PickaxeClient:


local ReplicatedStorage = game:GetService('ReplicatedStorage')
local RemotesFolder = ReplicatedStorage:WaitForChild('Remotes')
local GetDataRemoteFunction = RemotesFolder:WaitForChild('GetData')
local UpdateData = RemotesFolder:WaitForChild('UpdateData')

local player = game:GetService("Players").LocalPlayer
local Pickaxe = script.Parent
local PickaxeHandle = script.Parent.Handle

--local DataService = require(game.ServerStorage.Systems.DataService)

Pickaxe.Equipped:Connect(function()
	--local Weld = Instance.new("Weld")
	--Weld.Name = "PickaxeWeld"
	--Weld.Parent = player.Character.LeftHand
	
	--Weld.Part0 = player.Character.LeftHand
	--Weld.Part1 = PickaxeHandle
end)

resources = {}

local function IsPlayerInProximity(boolstatement)
	boolstatement = false
	--if player.Character.
	
	return boolstatement
end

local activeData = nil

Pickaxe.Activated:Connect(function(LocalPlayer, Object)
	local resourceItem = nil
	for i,v in pairs(game.Workspace.Collectables:GetChildren()) do
		resourceItem = v

		if (player:DistanceFromCharacter(v.Main.Position) <= 8) then
			local mouse = player:GetMouse()
			
			if mouse.Target.Name == "Main" then
				print("Collected +1 "..v.Name)
				activeData = GetDataRemoteFunction:InvokeServer()
				print(activeData)
				
				for itemID, quantity in pairs(activeData.Inventory) do
					print(activeData)
				end

			end
		end	
	end
end)

DataService:


local Players = game:GetService("Players")

local ServerStorage = game:GetService("ServerStorage")
local ServerModules = ServerStorage:WaitForChild("Modules")
local ProfileService = require(ServerModules:WaitForChild("ProfileService"))

local ProfileTemplate = {

	-- game values
	Cash = 0,
	Gems = 0,
	Quests = { },
	Inventory = { },

	-- analytic
	LogInTimes = 0,
	TotalGameTime = 0,
}

local GameProfileStore = ProfileService.GetProfileStore("PlayerData2", ProfileTemplate)

local Profiles = {}
local JoinTimes = {}

local function FloorNumber(number, decimalPlaces)
	decimalPlaces = decimalPlaces or 2 -- this is saying that if decimalPlaces is not given, just make it "2"
	return math.floor(number * math.pow(10, decimalPlaces)) / math.pow(10, decimalPlaces)
end

local function OnPostProfileLoad(player, profile)
	print(profile)
	profile.Data.LogInTimes += 1
	local totalLogins = profile.Data.LogInTimes
	print( string.format('%s has logged in %s time%s', player.Name, totalLogins, (totalLogins > 1) and 's' or '') )
	print( ' This player has played a total of ' ..profile.Data.TotalGameTime..' seconds before joining this server.' )
	for i, str in ipairs( profile.Data.Inventory ) do
		print(i, str)
		if profile.Data.Inventory[str] then
			profile.Data.Inventory[str] += 1
		else
			profile.Data.Inventory[str] = 1
		end
		table.remove(profile.Data.Inventory, i)
	end
	--					  ^				   ^	   ^------------------------.
	--			  player time here    specific login number here		time or time(s) depending on the number of login times
	-- ex)
	-- SPOOK_EXE has logged in 1 time.
	-- SPOOK_EXE has logged in 2 times.
	JoinTimes[player] = tick()
end

local function PlayerAdded(player)
	local profile = GameProfileStore:LoadProfileAsync(tostring(player.UserId))
	if profile then
		profile:AddUserId(player.UserId) -- GDPR compliance
		profile:Reconcile() -- putting all missing template values into the active data ( optional )
		profile:ListenToRelease(function()
			Profiles[player] = nil
			-- The profile could've been loaded on another Roblox server:
			player:Kick('Profile has been loaded onto another Server.')
		end)
		if player:IsDescendantOf(Players) then
			OnPostProfileLoad(player, profile)
			Profiles[player] = profile
		else
			-- Player left before the profile loaded:
			profile:Release()
		end
	else
		player:Kick('Failed to Load Data : OnPlayerAdded_1')
	end

end

--Lets say you have a Admin Panel and you try to edit the player's data, it will kick them from the server

-- // Module // --
local Module = {}

function Module:GetPlayerProfile(Player, Yield)
	local profile = Profiles[Player]
	if Yield and not profile then
		repeat task.wait(0.1)
			profile = Profiles[Player]
		until profile or (not Player.Parent)
	end
	return profile
end

function Module:Init()
	for _, player in ipairs(Players:GetPlayers()) do
		coroutine.wrap(PlayerAdded)(player)
	end
	Players.PlayerAdded:Connect(PlayerAdded)

	Players.PlayerRemoving:Connect(function(player)
		local profile = Profiles[player]
		if profile then
			--add the duration they've played to the data
			local duration = tick() - JoinTimes[player]
			--profile.Data.TotalGameTime += duration
			--profile.Data.TotalGameTime = FloorNumber(profile.Data.TotalGameTime, 3)
			--print( string.format('%s has played a total of %s seconds this session, totalling the total to %s seconds', player.Name, FloorNumber(duration), profile.Data.TotalGameTime))
			JoinTimes[player] = nil
			--release the profile so other games can load it
			profile:Release()
		end
	end)

end

return Module

Now I know this looks pretty dumb and you might ask, “Why are you trying to do this when the other functionality doesn’t work?” Well I will come back to fixing everything else, but right now I just want to update the player’s data.

Attached below is a video.

1 Like

just make a function that goes over the data and changes it in the gui, depending on the values im using a replicated folder with player data since this is better if i want other players to inspect players stats withoud having to call the server each time for the data, but that also an option

just make a local script change the items in the player depending on the values

Yeah a function to update the NUMBER “quantity of the item(s)” inside of the GUI would be good, and to have something else (I assume a script, but I also don’t know if this second part is what you meant), like a script listening for an event or actually changing on a changed event the data in the player’s inventory based off of the item’s value in the gui, like if the text label is a certain number then it should reflect that in the datastore. Got it.

But how do I actually do that? How do I specifically access that item? I’m having trouble figuring out how to write it. I know I want to say activeData… or something along the lines of that (obv), and I know I want to access the Inventory, and the data, and specifically that specific item that player interacted with. But I don’t know how I would write that.

Specifically, here:

I tried adding, activeData.Data.Inventory[v.Name] += 1 but it’s not working. Hopefully someone viewing might understand better what it is I am trying to do.

whit i did is create a folder in replicated storage with the playerID as a name on player added event

ReplicatedStorage>
useridhere(folder)
updateinventory(intvalue) = 0

every time the server changes the stats in the folder it increases the int value ‘update inventory’ by 1
so its 1 2 3 4 5 etc
why not a boolean and change it to false each time roblux weird and the local script doesnt detect it always

then have a local script

game.replicatedstorage[game.players.LocalPlayer.Userid].updateinventory.changed:connect(function() 
-- players inventory changed on server detected 
-- itterate over the player backpack item by item
-- then find the gui item and change it
most ez is make a guiitemslot that u can clone and put in backpack for each item it found in rep data
then u just delete the inventory gui holder so its empty clone for each item the gui and set the data
end)

u want an example that i do in my game

im honestly too lazy to write a code for that right now but i hope this gives u a bit of an idea on how to counter ur problem, sorry if its not helpfull enough

After some figuring out I managed to solve the problem of the data not getting updated. The value for the “GoldOre” inside of the data table does update to 8 after interacting with it. A new problem now is that it’s not actually saving. When I rejoin the game, and the table prints when the player’s added, it only says 7.

The other problem isn’t actually a problem, I can figure it out, but I will need to update the label inside of the inventory in order to actually represent the change in quantity of the specific item, in correspondence with the item’s value inside of the data’s table.

Videos attached below

saving issues can be because:

  • u din’t enable “Studio access to API services” (for datastore)
  • u are not testing it as a local server where u have a server window and client window or actually playing the game outside studio
  • reached limit of datastore request
  • using bad practice when saving

i don’t kow how advanced ur scripting is but i recommend not using vanilla save method for data loss
also skipping over datastore2 module it has flaws

most robust and best reliable way to save and load data is persistant module it locks profile to even preven duping

there are videos on how to set it up

1 Like

UHM after watching ur latest video i think it because ur changing players data in a local script that does not get replicated to the server so the server won"t save the new data?