How to make the server differentiate each client?

I’m making a gun script right now. It sends a remote event towards the server and the server does its thing with the code. There’s one problem, the ammo seems to be stored globally accross all clients as when one client uses the gun, the ammo will be subtracted for all clients and also when a client reloads, it yields all the other clients. I can’t use some solutions as it makes the script vulnerable to exploiters.
The script may be messy, but hold with me.

Server script:

game.Players.PlayerAdded:Connect(function(plr)
	task.wait(1)
	print("aaa")
	local rt = game:GetService("ReplicatedStorage"):WaitForChild(plr.Name.."Shoot")
	print("v nnbbb")
	local reloadrt = game.ReplicatedStorage.Reload
	local debris = game:GetService("Debris")
	local gunshot = game:GetService("SoundService"):WaitForChild("Gun Shot")
	local animation = Instance.new("Animation")
	animation.AnimationId = "rbxassetid://13112812781"
	local debounce = false
	local isnil = false
	local ammoout = false
	local configfolders = script.Configuration
	local reload = game.SoundService["Reload Sound"]
	rt.OnServerEvent:Connect(function(plr, mouse, tool,pos)
		print("aaadfsss")
		local bullets = plr.Bulletpack.Bullet
		local char = plr.Character
		local hum = char.Humanoid
		local animator = hum.Animator
		local effect = tool.Effect.MuzzleEffect
		local foundchild = configfolders:FindFirstChild(tool.Name)
		local damagedebounce = false
		if debounce == false and bullets.Value > 0 and ammoout == false then 
			bullets.Value -=1
			print(bullets.Value)
			foundchild.Ammo.Value -=1
			print(foundchild.Ammo.Value)

			local animationid = foundchild:WaitForChild("AnimId").Value
			local reloadanimationid = foundchild.ReloadAnim.Value
			local animation = Instance.new("Animation")
			animation.AnimationId = animationid 
			local animator = plr.Character.Humanoid.Animator
			local loadanim = animator:LoadAnimation(animation)
			loadanim:Play()
			effect.Enabled = true
			gunshot:Play()
			if foundchild.Ammo.Value == 0 then
				reload:Play()
				print(foundchild.Ammo.Value)
				local animationreload = Instance.new("Animation")
				animationreload.AnimationId = reloadanimationid
				local loadanim = animator:LoadAnimation(animationreload)
				loadanim:Play()
				ammoout = true
				effect.Enabled = false
				while true do
					foundchild.Ammo.Value = 0
					debounce = true
					task.wait()
					debounce = false
					break
				end
				if foundchild.Ammo.Value >=  bullets.Value then
					foundchild.Ammo.Value = bullets.Value
				else
					foundchild.Ammo.Value = foundchild.MaxAmmo.Value

				end
				reload:Stop()
				ammoout = false
			end

			debounce = true
			if mouse == nil then 
				task.wait(foundchild.FireRate.Value)
				gunshot:Stop()
				debounce = false
				effect.Enabled = false
				return
			end

			if mouse.Parent:FindFirstChild("Humanoid")  then
				mouse.Parent.Humanoid:TakeDamage(foundchild.Damage.Value)
			elseif mouse.Parent.ClassName == "Accessory" then
				mouse.Parent.Parent.Humanoid:TakeDamage(foundchild.Damage.Value)
			end
			task.wait(foundchild.FireRate.Value)
			print(foundchild.FireRate.Value)
			gunshot:Stop()
			debounce = false
			effect.Enabled = false
		end
	end)
end)
1 Like

This is because you have 2 plr variables under the same function. You need to move the OnServerEvent function out of the PlayerAdded function to avoid this issue. You also do not need to name the RemoteEvent as the player’s name, as that will cause confusion and possibly other issues, one RemoteEvent with a simple name is enough.

1 Like

This didn’t work unfortunately, this broke the server instead.

Could you please show your current code?

game.Players.PlayerAdded:Connect(function(plr)
	task.wait(1)
	print("aaa")
	rt = game:GetService("ReplicatedStorage"):WaitForChild(plr.Name.."Shoot")
	print("v nnbbb")
	 reloadrt = game.ReplicatedStorage.Reload
 debris = game:GetService("Debris")
	 gunshot = game:GetService("SoundService"):WaitForChild("Gun Shot")
	 animation = Instance.new("Animation")
	animation.AnimationId = "rbxassetid://13112812781"
	 debounce = false
	 isnil = false
	 ammoout = false
	 configfolders = script.Configuration
	 reload = game.SoundService["Reload Sound"]
end)
rt.OnServerEvent:Connect(function(plr, mouse, tool,pos)
	print("aaadfsss")
	local bullets = plr.Bulletpack.Bullet
	local char = plr.Character
	local hum = char.Humanoid
	local animator = hum.Animator
	local effect = tool.Effect.MuzzleEffect
	local foundchild = configfolders:FindFirstChild(tool.Name)
	local damagedebounce = false
	if debounce == false and bullets.Value > 0 and ammoout == false then 
		bullets.Value -=1
		print(bullets.Value)
		foundchild.Ammo.Value -=1
		print(foundchild.Ammo.Value)

		local animationid = foundchild:WaitForChild("AnimId").Value
		local reloadanimationid = foundchild.ReloadAnim.Value
		local animation = Instance.new("Animation")
		animation.AnimationId = animationid 
		local animator = plr.Character.Humanoid.Animator
		local loadanim = animator:LoadAnimation(animation)
		loadanim:Play()
		effect.Enabled = true
		gunshot:Play()
		if foundchild.Ammo.Value == 0 then
			reload:Play()
			print(foundchild.Ammo.Value)
			local animationreload = Instance.new("Animation")
			animationreload.AnimationId = reloadanimationid
			local loadanim = animator:LoadAnimation(animationreload)
			loadanim:Play()
			ammoout = true
			effect.Enabled = false
			while true do
				foundchild.Ammo.Value = 0
				debounce = true
				task.wait()
				debounce = false
				break
			end
			if foundchild.Ammo.Value >=  bullets.Value then
				foundchild.Ammo.Value = bullets.Value
			else
				foundchild.Ammo.Value = foundchild.MaxAmmo.Value

			end
			reload:Stop()
			ammoout = false
		end

		debounce = true
		if mouse == nil then 
			task.wait(foundchild.FireRate.Value)
			gunshot:Stop()
			debounce = false
			effect.Enabled = false
			return
		end

		if mouse.Parent:FindFirstChild("Humanoid")  then
			mouse.Parent.Humanoid:TakeDamage(foundchild.Damage.Value)
		elseif mouse.Parent.ClassName == "Accessory" then
			mouse.Parent.Parent.Humanoid:TakeDamage(foundchild.Damage.Value)
		end
		task.wait(foundchild.FireRate.Value)
		print(foundchild.FireRate.Value)
		gunshot:Stop()
		debounce = false
		effect.Enabled = false
	end
end)

Could you please further explain what exactly isn’t working now? Are you receiving any errors or warnings in the output? If so, could you please state them?
One thing to note, you are creating global variables inside a function, which should not be the case, and may likely be the cause of the problem.

Before using my updated version of your code, rename your RemoteEvent to ‘Shoot’.

Updated Code:

local rt = game:GetService("ReplicatedStorage"):WaitForChild("Shoot")
local reloadrt = game.ReplicatedStorage.Reload
local debris = game:GetService("Debris")

--game.Players.PlayerAdded:Connect(function(plr)
--	task.wait(1)
--	print("aaa")
--	print("v nnbbb")
--end)

rt.OnServerEvent:Connect(function(plr, mouse, tool,pos)
	print("aaadfsss")
	
	local debounce = false
	local isnil = false
	local ammoout = false
	local configfolders = script.Configuration
	
	local reload = game.SoundService["Reload Sound"]
	local gunshot = game:GetService("SoundService"):WaitForChild("Gun Shot")
	
	local bullets = plr.Bulletpack.Bullet
	local char = plr.Character
	local hum = char.Humanoid
	local animator = hum.Animator
	local effect = tool.Effect.MuzzleEffect
	local foundchild = configfolders:FindFirstChild(tool.Name)
	local damagedebounce = false
	
	if debounce == false and bullets.Value > 0 and ammoout == false then 
		bullets.Value -=1
		print(bullets.Value)
		print(foundchild.Ammo.Value)
		
		local animation = Instance.new("Animation")
		animation.AnimationId = "rbxassetid://13112812781"
		
		local animationid = foundchild:WaitForChild("AnimId").Value
		local reloadanimationid = foundchild.ReloadAnim.Value
		
		local animation = Instance.new("Animation")
		animation.AnimationId = animationid 
		local animator = plr.Character.Humanoid.Animator
		local loadanim = animator:LoadAnimation(animation)
		loadanim:Play()
		
		effect.Enabled = true
		gunshot:Play()
		if foundchild.Ammo.Value == 0 then
			reload:Play()
			print(foundchild.Ammo.Value)
			local animationreload = Instance.new("Animation")
			animationreload.AnimationId = reloadanimationid
			local loadanim = animator:LoadAnimation(animationreload)
			loadanim:Play()
			ammoout = true
			effect.Enabled = false
			while true do
				foundchild.Ammo.Value = 0
				debounce = true
				task.wait()
				debounce = false
				break
			end
			if foundchild.Ammo.Value >=  bullets.Value then
				foundchild.Ammo.Value = bullets.Value
			else
				foundchild.Ammo.Value = foundchild.MaxAmmo.Value

			end
			reload:Stop()
			ammoout = false
		end

		debounce = true
		if mouse == nil then 
			task.wait(foundchild.FireRate.Value)
			gunshot:Stop()
			debounce = false
			effect.Enabled = false
			return
		end

		if mouse.Parent:FindFirstChild("Humanoid")  then
			mouse.Parent.Humanoid:TakeDamage(foundchild.Damage.Value)
		elseif mouse.Parent.ClassName == "Accessory" then
			mouse.Parent.Parent.Humanoid:TakeDamage(foundchild.Damage.Value)
		end
		task.wait(foundchild.FireRate.Value)
		print(foundchild.FireRate.Value)
		gunshot:Stop()
		debounce = false
		effect.Enabled = false
	end
end)

I’m not receiving any warnings or errors in my output, it’s just print statements that tell me it won’t listen to the event. I will use your updated piece of code

Unfortunately your piece of code still didn’t work.
As in the gun worked but the same issue I explained in this topic occured.

I’m still a little confused as to what issue is occurring for you. From my understanding, some (or all) of the print statements don’t print? But the gun still functioned properly?
If some of the print statements did not print, could you state which ones didn’t?

No, like I said the gun works fine but like I said in the topic, it seems to be that the ammo is stored on the server and when one client uses the gun, it subtracts for the other clients. I want to make it to the clients have their own individual ammo in the server and own individual reloading.

I’ve just looked through the script again, and might have found another issue. But before I state it, I just want to confirm, where is this Server Script located?

The server script is located in server script service

foundchild.Ammo.Value -=1

why are you changing the config folder’s bullet? just remove this line and let us know if it fixes it. all you should use is the bullets.Value -=1, which is the player’s backpack bullet

1 Like

Unfortunately there’s no other way to store it. I’ll try think of a way but using a variable will lead to the script resetting the variable over and over again.

How would I make a variable to store the ammo that wouldn’t reset itself over and over again?

This wouldn’t be possible without an IntValue or NumberValue.

Looking back at your system, however, why not just have the Ammo value for the tool under the tool itself rather than having it as a descendant of ServerScriptService? In fact, why not just have the whole configuration folder under each tool?
The main issue is the fact that the game only uses that one configuration folder for every single tool anyone else is using, and that is what’s causing everyone’s gun to change its ammo whenever it’s changed by one person.

Parent the Configuration folder (from the Server Script) to its desired tool that uses it (I’m pretty sure you have a Configuration folder for every gun you have, named after the gun’s name). Remember to rename each configuration folder (that has its name as the gun’s name) to “Configuration” (this is to avoid confusion when trying to get the Configuration folder from the tool), and make sure all the values existing values stay.
Then all you have to do is change a bit of the variables in the Server Script.

After you parent the Configuration folder, use the following updated code for your Server Script:

local rt = game:GetService("ReplicatedStorage"):WaitForChild("Shoot")
local reloadrt = game.ReplicatedStorage.Reload
local debris = game:GetService("Debris")

--game.Players.PlayerAdded:Connect(function(plr)
--	task.wait(1)
--	print("aaa")
--	print("v nnbbb")
--end)

rt.OnServerEvent:Connect(function(plr, mouse, tool,pos)
	print("aaadfsss")
	
	local debounce = false
	local isnil = false
	local ammoout = false
	local ConfigurationFol = tool:FindFirstChild("Configuration") -- must be under the desired tool
	
	local reload = game.SoundService["Reload Sound"]
	local gunshot = game:GetService("SoundService"):WaitForChild("Gun Shot")
	
	local bullets = plr.Bulletpack.Bullet
	local char = plr.Character
	local hum = char.Humanoid
	local animator = hum.Animator
	local effect = tool.Effect.MuzzleEffect

	-- Configuration Values
	local AmmoValue = ConfigurationFol:FindFirstChild("Ammo")
	local MaxAmmoValue = ConfigurationFol:FindFirstChild("MaxAmmo")
	local DamageValue = ConfigurationFol:FindFirstChild("Damage")
	local FireRateValue = ConfigurationFol:FindFirstChild("FireRate")
	local AnimIdValue = ConfigurationFol:FindFirstChild("AnimId")
	local ReloadAnimValue = ConfigurationFol:FindFirstChild("ReloadAnim")

	local damagedebounce = false
	
	if debounce == false and bullets.Value > 0 and ammoout == false then 
		bullets.Value -=1
		print(bullets.Value)
		print(AmmoValue.Value)
		
		local animation = Instance.new("Animation")
		animation.AnimationId = "rbxassetid://13112812781"
		
		local animationid = AnimIdValue.Value
		local reloadanimationid = ReloadAnimValue.Value
		
		local animation = Instance.new("Animation")
		animation.AnimationId = animationid

		local animator = plr.Character.Humanoid.Animator
		local loadanim = animator:LoadAnimation(animation)
		loadanim:Play()
		
		effect.Enabled = true
		gunshot:Play()

		if AmmoValue.Value == 0 then
			reload:Play()
			print(AmmoValue.Value)

			local animationreload = Instance.new("Animation")
			animationreload.AnimationId = reloadanimationid

			local loadanim = animator:LoadAnimation(animationreload)
			loadanim:Play()

			ammoout = true
			effect.Enabled = false

			while true do
				AmmoValue.Value = 0
				debounce = true
				task.wait()

				debounce = false
				break
			end

			if AmmoValue.Value >=  bullets.Value then
				AmmoValue.Value = bullets.Value
			else
				AmmoValue.Value = MaxAmmoValue.Value
			end

			reload:Stop()
			ammoout = false
		end

		debounce = true
		if mouse == nil then 
			task.wait(FireRateValue.Value)

			gunshot:Stop()
			debounce = false
			effect.Enabled = false
			return
		end

		if mouse.Parent:FindFirstChild("Humanoid")  then
			mouse.Parent.Humanoid:TakeDamage(DamageValue.Value)
		elseif mouse.Parent.ClassName == "Accessory" then
			mouse.Parent.Parent.Humanoid:TakeDamage(DamageValue.Value)
		end

		task.wait(FireRateValue.Value)
		print(FireRateValue.Value)

		gunshot:Stop()
		debounce = false
		effect.Enabled = false
	end
end)