Server age countdown behaves like it's client-sided, even though it's a server script

I will say, os.clock is wayy more accurate than time.

For instance,

print(
    os.clock() == os.clock() --> false
)

print(
    time() == time() --> true
)

I have heard that time is planned to be deprecated, but can’t actually confirm, so don’t take my words for it. But for most cases, os.clock is the thing for the job.

I don’t know much of converting time (i’m horrible at math), but:

would this be better?

local hour = math.floor(started / 3600)
local minutes = math.floor(started % 3600)
local seconds = ---? I don't know how to calculate this, just a second. WHY IS STUDIO INSTALLING WHAT

In my reply I stated it doesn’t matter, because he isn’t looking for precision past minutes

tick is going to be deprecated in favor of os.time, time, and os.clock.

1 Like

yea, normally server age doesn’t even need precision past minutes

1 Like

It’s entirely dependent on what level of precision you want. I don’t think it’s an adopted concept that when displaying age you don’t “need” precision past minutes.

If this is true, then yes, please use os.clock()

You need have a value / attribute that kept somewhere maybe in workspace, replicatedstorage, whatever, which keeps the a os.time value of when the server launched! (must be os.time).

Then, you can use that to calculate the time properly on the client.

Something like this could work;

--\\ Client

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local start = ReplicatedStorage:WaitForChild("ServerCreatedTime") and ReplicatedStorage.ServerCreatedTime.Value

game:GetService("RunService").Heartbeat:Connect(function()
    local started = os.time() - start       
 
    local min = math.floor(started / 60)

	local sec = math.floor(started % 60)

	local hr = math.floor(min - min % 60) / 60

	script.Parent.Time.Text = string.format("Server age: %.2d:%.2d:%.2d", hr, min, sec)
end)

Sleitnick has advised against os.clock except in Studio for benchmarking purposes. I’ll see if I can dig up a reference.

Here you go. It’s not super enlightening, but it’s well-worded and from what I would consider a primary source.


Devhub api reference

1 microsecond is WAY too precise for something like server age

But unfortunately that doesn’t say anything about performance or stability consequences if you use it in your game.

This is only one way of doing it, and it’s not preferred. Attributes are intended to pertain to the instances they’re assigned to. In my reply, the best way to handle replication for this would be to use RemoteEvents.

Sorry I don’t know what that means.

Why though…? I’m still confused.

Please don’t do this.

Attributes are intended to pertain to the instances they’re assigned to. Workspace is a container holding all of the game’s view geometry. It does not make sense and is horrid practice to just chuck an attribute under Workspace that relates to something completely different from geometry simply for the sake of easiness and having Roblox handle replication for you.

RemoteEvents were created specifically for networking and communication, and are meant for these kinds of things.

Being in this mindset of relying on attributes for replication introduces code smell, and you wind up running into bugs that take a lot of resources to fix!

Additionally, it would be more resource-conscious if the client asked for the value one time and then handled the counting itself. Continuously polling the server or continuously giving information to clients consumes lots of bandwidth.

You can use BaseValues too? (and on ReplicatedStorage) That’s essentially what I did.

It’s just fine for the most part, you don’t need to handle replication for it then, what’s the problem with using that?

But oh my god. Yes, I agree with you then, but that’s not what I mean.

I mean just creating a os.time IntValue object inside ReplicatedStorage when the server launches, that value is NOT updated ever, it’s only set once so that clients can grab it and know when the server actually started. The counting is only handled by the client then.

ValueBases are even worse. They’re artifacts of the older engine and are just more shortcuts. It’s a highly concerning problem and extremely dangerous mindset to get into that entraps newer developers.

By using ValueBases you’re telling Roblox to listen for event connections and add unnecessary instance metadata that consumes more resources.

For anyone reading this, I highly suggest you take in this golden advice:
Don’t use ValueBases. Please.

“It’s just fine” is not the problem. It’s bad practice and should not be used if a better and more granular solution exists.

This bickering is clogging up the thread and I provided more than enough information in my replies, including some good long-term advice, to help OP solve his problem.

What’s wrong with them? It’s like rejecting something just because it’s a bit old, BaseValues aren’t bad? They just hold values and that’s fine.

Then you can just use attributes.

Using RemoteEvents / Functions are still instances, give you the almost same result, there’s meta-data like Names, etc. It’s not much different than a ValueBase or Attribute.

Plus it’s not like .Changed connections are polling every frame or something. That’s just not how events work, and it wouldn’t change anything anyhow. The value or anything on it is not changing.

Yes I agree, but also please just edit your existing replies to add what you wanna say instead of making a completely new reply then.

Yes that is true, but that’s not what were doing here. It’s only one value keeping a os.time value, and that’s that.

Same with Remotes, they end up being the same thing, and just being more annoying to code.

In my reply, I explained a multitude of things wrong with them.

It’s not. I’m not advising against ValueBases simply because of their age. ValueBases have a ton of caveats and are almost always misused. Better and more robust solutions exist to keep track of information.

ValueBases are instances so they have a plethora of metadata attached to them that the engine needs to keep track of. With a few ValueBases this is negligible in terms of the performance difference, but if you’re excessively using them, it can become concerning.

You don’t need 95% of this metadata when using ValueBases, so essentially you’re creating more information than you need. Why would you ever do this?

ValueBases appeal so much to newer developers because of their ease of use, and they begin to adopt them as they grow. It’s not talked about much and usually takes a long time before you realize how bad they are.

I literally explained the issue with using attributes for this use case.

1 Like

I for some reason didn’t think of using values… Anyway, this mostly helped me out, alongside @riverman56’s replies, which were pretty useful. I apologize for keeping you waiting, I was offline for most of the day.

1 Like