How to fix client to server issue

Im trying to make a timer that is currently client sided to become server sided.

script(local, inside the starter guis frame)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Event = ReplicatedStorage:WaitForChild("TimerEvent")
local Timer = script.Parent
local Minutes = 2
local Seconds = 5

Event.OnClientEvent:Connect(function()
	repeat
		if Seconds <= 0 then
			Minutes = Minutes - 1
			Seconds = 59
		else
			Seconds = Seconds - 1
		end
		if Seconds <= 9  then
			Timer.Text = tostring(Minutes)..":0"..tostring(Seconds)
		else
			Timer.Text = tostring(Minutes)..":"..tostring(Seconds)
		end
		wait(1)
	until Minutes <= 0 and Seconds <= 0
end)

script(server, serverscriptservice)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Event = ReplicatedStorage:WaitForChild("TimerEvent")

Event:FireAllClients()

there is no issue in the output. The timer does not even play. It did play before i tinkered with it to become server sided.

Not critical in this case but always remember client stuff can be tinkered with so ensure that the timer is purely visual and all event timers are done on the server.

Two things that could be the problem:
A. The timer GUI object (which I assume is a textlabel) is not the script.parent as you say its in the GUI frame

B. Your FireAllClients call is not going into the events queue therefore your client is missing it before it loads.

Edit: wait might also go deprecated so task.wait() is a the proper method :wink:

Edit 2: From my testing it appears to be problem B but depending on where your local script is, it might be both (although A would make an error I am assume)

1 Like

would i write it like this

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Event = ReplicatedStorage:WaitForChild("TimerEvent")
task.wait()
Event:FireAllClients()

it doesn’t seem to work(how I wrote it)

Yes that is how task.wait() is used and in this case you need to wait for the client to load in before you fire the clients. If this was a minigame that would use the timer after the player was in it works, but for debugging or for an instant countdown when the player loads in, you need to yield until the player has fully loaded.

You might try something like this without any events you may not need them at all setup the server with a script like this using attributes and attribute signal changes to connect a function on the client that updates the UI

server side script just adds 1 second on each loop and sets to attribute on workspace for all clients to see

while wait(1) do
	local CurrentTime = workspace:GetAttribute('Timer') or 0  -- gets current time if not set yet just starts at 0
	workspace:SetAttribute('Timer', CurrentTime + 1)  -- add 1 second each loop to the timer
end

local side script gets the signal/value change and formats and updates clients timer text

local Timer = script.Parent
local Minutes = 2  -- may not need this now
local Seconds = 5

workspace:GetAttributeChangedSignal('Timer'):Connect(function()
	local NewTime = ''  -- incase not changed
	local Timer = workspace:GetAttribute('Timer') or '0'  -- load time or 0
	local CurrentTime =  os.date("!*t",Timer)  -- formats to hours mins seconds
	if CurrentTime.min > 0 then
		NewTime = NewTime .. CurrentTime.min .. 'm '
	end
	print(NewTime .. CurrentTime.sec .. 's ')  -- can remove this after you see it works
	Timer.Text = NewTime .. CurrentTime.sec .. 's '  -- add seconds even if 0
end)

oh and if you need to reset the timer to 0 you can just do this on server somewhere

workspace:SetAttribute('Timer', 0)
1 Like