I have tried multiple methods of getting player’s local time but all of which seem to based on the time on the player’s device which the player can modify easily. Is there a way to get around this?
I’m trying to make a daily mission system that resets at the end of the player’s day.
Maybe u can use datastores to make it so that you can get the UTC time or something when they joined and claimed the reward and when they join back calculate how much it had been since they had last joined. If it’s 24 hours or more then reset it.
Theres no foolproof way to do this (since vpns and stuff literally exist), but perhaps take a try with localization service? (you can get the country of the player, which you can then use to find the timezone)
To get the players local time you just need to call… local localTime = os.date(“*t”).
The only real “trick” to this is to call that from a local (client) script.
If the client is determined enough, they can always find ways to hide their actual date and time. To make sure that they aren’t able to receive a reward unless a day has passed, you’ll need to check the time on the server-side, which you can do so as follows:
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local dataStore = DataStoreService:GetDataStore("Example")
local canSave = {}
Players.PlayerAdded:Connect(function(player)
local success, data = pcall(dataStore.GetAsync, dataStore, player.UserId)
if success then
canSave[player] = true
if data then
if (DateTime.now().UnixTimestamp - data.Time) >= 86400 then -- 86400 is 1 day in seconds
-- A day has passed since this player joined the game
else
-- Not enough time has passed for the daily reward
end
else
-- Handle logic for first-time player
end
else
warn(`Failed to get data for Player {player.UserId} ({player.DisplayName})\nError: {data}`)
end
end)
local function saveData(player)
if canSave[player] then
canSave[player] = nil
local data = {
Time = DateTime.now().UnixTimestamp -- Save the current time at the moment the player leaves the game
}
local success, error = pcall(dataStore.SetAsync, dataStore, player.UserId, data)
if success then return end
warn(`Failed to save data for Player {player.UserId} ({player.DisplayName})\nError: {error}`)
end
end
Players.PlayerRemoving:Connect(saveData)
game:BindToClose(function()
if RunService:IsStudio() then
task.wait(1)
else
local x, y = 0, 0
for _, player in Players:GetPlayers() do
x += 1
task.spawn(function()
saveData(player)
y += 1
end)
end
repeat task.wait() until y == x
end
end)
A possible solution is to use the Roblox game’s internal clock, which is synchronized across all players. You can access this internal clock using the game:GetService("Clock") API.
Here’s an example of how you can use the internal clock to determine the player’s day:
local ClockService = game:GetService("Clock")
-- Get the player's local time
local playerTime = game.Players.LocalPlayer.ClockTime
-- Get the internal clock's current time
local internalTime = ClockService:GetTime()
-- Calculate the difference between the two times
local timeDifference = internalTime - playerTime
-- If the time difference is greater than a certain threshold (e.g., 24 hours), reset the player's daily mission progress
if timeDifference > 86400 then
-- Reset daily mission progress here
end
This code gets the player’s local time and the internal clock’s current time, then calculates the difference between the two. If the difference is greater than 24 hours (86400 seconds), it resets the player’s daily mission progress.
Note that this method is more secure than relying on the player’s local time, as it’s harder for players to modify the internal clock. However, it’s not foolproof, as a player could potentially exploit a bug or glitch in the game’s clock system.
Also, keep in mind that this method only works if the game is running on a Roblox server that supports the ClockService API.
You can use client time to determine the next reward time and UTC time as a 24 hour minimum timer so clients cannot get an award early. Only issue is this will prevent roaming players from getting an award when they legimately move to a time zone that’s in the future past that reward timestamp.