DataStore Not Working (Group Game)

It’s a local script. How can I fire a remote event to update the value?

i advise you update the data on the server doing it on client can make your game vulnerable to exploits.

Why is it a local script? Data stores only work towards the server, I recommend putting it in serverscriptservice as a (server)script. Make sure you define everything correctly too, and keep your output out so it can help you towards fixing things.

Judging by the fact that the saving script isn’t actually erroring, the save script itself is probably on the server. I believe the issue is that they’re using ContextActionService or UserInputService to decide when to update the values, which can only be done in a LocalScript, while the values can only be properly updated on the server. They’ll need to add some form of communication via RemoteEvents to tell the server to update the values.

Ok then, that would make sense, so I would go with what you are announcing to him.

I did this, but it doesn’t seem to work. Basically I replaced the part of the script that added one to the flex from the local script into the script to fire the server,

and on the script in server script service I wrote this

local Player = game.Players.LocalPlayer

local Flex = Player.leaderstats.Flex.Value

game.ReplicatedStorage.Flex.OnServerEvent:Connect(function(player)

Flex.Value = Flex.Value + 1

end)

Edit – figured it out. Your example script actually worked.

Here’s some test code using DS2, it’s a lot easier to use and I suggest getting used to it.

Sorry if this doesn’t solve your problem.


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlayerData = require(ReplicatedStorage.PlayerData)
local MainKey = "NY_"

local Rounds = require(script.RoundHandler)

PlayerData.Combine(MainKey, "Stats", "Misc")

local function SetDefault()
	
	local Dictionary = {
		
		Stats = {
			
			["Cash"] = 0;
			["Wins"] = 0;	
			
		},
		Misc = {
			
			["MetTheOwner"] = false;	
			["AlphaTester"] = false;
			
		},
		
	}
	return Dictionary
	
end

game.Players.PlayerAdded:Connect(function(Player)
	
	local UserData = PlayerData(MainKey, Player):Get(SetDefault())
	
	--[[ STATS ]]--
	
	local PlrStats = Instance.new("Folder", Player)
	PlrStats.Name = "leaderstats"
	
	local Cash = Instance.new("IntValue", PlrStats)
	Cash.Name = "Cash"
	
	local Wins = Instance.new("IntValue", PlrStats)
	Wins.Name = "Wins"
	
	--[[ AWARDS/MISC ]]--
	
	local MiscFolder = Instance.new("Folder", Player)
	MiscFolder.Name = "Misc"
	
	local MetTheOwner = Instance.new("BoolValue", MiscFolder)
	MetTheOwner.Name = "MetTheOwner"
	
	local AlphaTester = Instance.new("BoolValue", MiscFolder)
	AlphaTester.Name = "AlphaTester"
	
	--[[ LOADING/SAVING ]]--
	
	local StatsSave = PlayerData("Stats", Player)
	local MiscSave = PlayerData("Misc", Player)
	
	local function UpdateStats(New)
		Cash.Value = StatsSave:Get(New).Cash
		Wins.Value = StatsSave:Get(New).Wins
	end
	
	local function UpdateMisc(New)
		MetTheOwner.Value = MiscSave:Get(New).MetTheOwner
		AlphaTester.Value = MiscSave:Get(New).AlphaTester
	end
	
	--[[ UPDATING ]]--
	
	UpdateStats(UserData.Stats)
	UpdateMisc(UserData.Misc)
	
	StatsSave:OnUpdate(UpdateStats)
	MiscSave:OnUpdate(UpdateMisc)
	
	--spawn(function()
		--while(true)do
			--UserData.Stats.Cash = UserData.Stats.Cash + 5
			--StatsSave:Set(UserData.Stats)
			--if UserData.Misc.AlphaTester == false then
				--UserData.Misc.AlphaTester = true
				--MiscSave:Set(UserData.Misc)
				--print(UserData.Misc.AlphaTester)
			--end
			--wait(1)
		--end
	--end)
	
	--[[ ETC ]]--
	
end)

No, don’t do that. Don’t EVER give the client any power. Don’t even suggest that, because that is incorrect and risky. We don’t want beginner scripters looking for a quick fix to their problem to see that, and just do that until they learn better.

2 Likes

Okay… so how can I create a script that will update the servers values without giving the client power…

Follow what @RainScripts said, except probably don’t put DataStore2 in ReplicatedStorage and don’t do Instance.new(ClassName, Parent).

1 Like

Well that won’t work, because the you increase flex value when the key e is pressed, which also toggles and animation so it needs to be under starter character

Use Postie to invoke the client when the client supposedly presses E to check if they have actually pressed it.

Server:

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

local DataStore2 = require(ServerStorage.DataStore2)
local Postie = require(ReplicatedStorage.Postie)
local GameEvent = ReplicatedStorage.GameEvent -- Your RemoteEvent.

DataStore2.Combine("MainDataStore", "PointsData")

local INCREMENT_POINTS_KEY = Enum.KeyCode.E
local INCREMENT_POINTS_BY = 1
local MAX_STRIKES = 3

local PlayerStrikes = {}

local EventCalls = {
	PlayerPressedE = function(Player)
		local Success, PressedKey = Postie.InvokeClient("GetPressedKey", Player, 0.25)
		local PassedCheck = Success and PressedKey == INCREMENT_POINTS_KEY

		if PassedCheck then
			local PointsData = DataStore2("PointsData", Player)
			PointsData:Increment(INCREMENT_POINTS_BY)
		else
			PlayerStrikes[Player] = PlayerStrikes[Player] + 1
			if PlayerStrikes[Player] >= MAX_STRIKES then
				Player:Kick("Failed to provide last used key properly three times.")
			end
		end
	end;
}

local function OnUpdateFenv(ValueObject)
	return function(Value)
		ValueObject.Value = Value
	end
end

local function PlayerAdded(Player)
	if not Player:FindFirstChild("leaderstats") then
		PlayerStrikes[Player] = 0

		local PointsData = DataStore2("PointsData", Player)

		local Leaderstats = Instance.new("Folder")
		Leaderstats.Name = "leaderstats"

		local Points = Instance.new("IntValue")
		Points.Name = "Points"
		Points.Value = PointsData:Get(0)
		Points.Parent = Leaderstats

		Leaderstats.Parent = Player

		PointsData:OnUpdate(OnUpdateFenv(Points))
	end
end

local function PlayerRemoving(Player)
	if PlayerStrikes[Player] then
		PlayerStrikes[Player] = nil
	end
end

local function OnServerEvent(Player, FunctionCall, ...)
	local Function = EventCalls[FunctionCall]
	if Function then Function(Player, ...) end
end

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)
GameEvent.OnServerEvent:Connect(OnServerEvent)
for _, Player in ipairs(Players:GetPlayers()) do PlayerAdded(Player) end

Client:

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

local Postie = require(ReplicatedStorage.Postie)
local GameEvent = ReplicatedStorage.GameEvent -- Your RemoteEvent.

local REMOVAL_TIME = 0.85
local LastPressedKey = nil
local AlreadyQueued = false

local function ResetKey()
	if AlreadyQueued then
		LastPressedKey = nil
		AlreadyQueued = false
	end
end

local function InputBegan(InputObject, GameProcessed)
	-- I'm not sure how you have it working right now, but I'll assume this,
	if not GameProcessed and InputObject.UserInputType == Enum.UserInputType.Keyboard and InputObject.KeyCode == Enum.KeyCode.E then
		LastPressedKey = InputObject.KeyCode
		GameEvent:FireServer("PlayerPressedE")

		if not AlreadyQueued then
			AlreadyQueued = true
			delay(REMOVAL_TIME, ResetKey)
		end
	end
end

local function GetPressedKey()
	return LastPressedKey
end

UserInputService.InputBegan:Connect(InputBegan)
Postie.SetCallback("GetPressedKey", GetPressedKey)

Made a mistake, my bad.

1 Like

Why would you not use Instance.new(ClassName, Parent)

I’d also rather DS2 the module or put it in ServerStorage but either would do.

ServerStorage is better so the client can’t even see it. And Instance.new(ClassName, Parent) is much slower than setting the parent last.

1 Like

They won’t be able to change anything either way, but like I said:

I’d also rather DS2 the module or put it in ServerStorage but either would do. <

Also, I don’t see any performance issues with it being slower at all, i’ve actually done both methods and each on relatively big games?

With their specific scenario, that’s really the only option. There’s no other way to access the user’s inputs without getting the client involved.

My hacky solution kinda says otherwise, but it’s only mildly better than the client, I’m sure.

1 Like

It is slower as shown by my benchmark, and as well as what zeuxcg said.

1 Like

I’m laughing so hard right now, two tenths of a second.

Ok, I see.

Here is some articles explaining the issue. Set other properties before Parent after Instance.new and PSA: Don't use Instance.new() with parent argument
2/10 of a second isn’t much, but imagine instancing multiple objects into your game. This time only increases with the more properties the object has, for instance, parts, which can cause significant delays.