I’m trying to create a chest system which should reset every 6 hours. I’m not sure if it’s not data saving, or there’s something wrong with my script but it doesn’t seem to save the time once the player leaves?
Serverscript
local DS = game:GetService("DataStoreService")
local RS = game:GetService("ReplicatedStorage")
function DailyReward(v)
local Player = game.Players:GetPlayerByUserId(v)
local MainCurrency = Player:WaitForChild("MainCurrency")
local Gems = MainCurrency:FindFirstChild("Gems")
if MainCurrency then
Gems.Value = Gems.Value + 15
end
end
game.ReplicatedStorage.Chests.GChest.OnServerEvent:Connect(function(plr, mode)
if (mode == "Group_R") then
print("Mode Correct")
if plr:IsInGroup(6154443) then
local Data = DS:GetDataStore("DailyRewards_V.1", plr.UserId)
local timeleft = Data:GetAsync("TimeLeft")
local hours = os.time() + 10800 --Time in seconds, default is 24 hours
warn(timeleft, hours, Data)
if timeleft == nil then
Data:SetAsync("TimeLeft", hours)
Data:IncrementAsync("Amount", 1) --Amount of times the player got the reward
DailyReward(plr.UserId)
else
local timeleft = tonumber(timeleft)
if (timeleft > 0 and timeleft - os.time() > 0) then
DailyReward(plr.UserId)
end
end
end
end
end)
--[[game.ReplicatedStorage.Chests.GetTime.OnServerInvoke = function(player)
warn("Invoked")
if player:IsInGroup(6154443) then
local Data = DS:GetDataStore("DailyRewards_V.1", player.UserId)
local timeleft = Data:GetAsync("TimeLeft")
local timeleft2 = tonumber(timeleft)
local hours = os.time() + 10800
warn("Sending Time")
return hours, timeleft
end
end]]--
game.ReplicatedStorage.Chests.GetTime.OnServerInvoke = function(player)
local Data = DS:GetDataStore("DailyRewards_V.1", player.UserId)
local timeleft = Data:GetAsync("TimeLeft")
local hours = os.time() + 10800
warn(timeleft, hours, Data)
return hours, timeleft, Data
end
The remote event sends the time to the player and the remote event gives the reward if the time is right. The thing is that the time sent is always 3:00:00.
Localscript which displays the time
local target, timeleft = game.ReplicatedStorage.Chests.GetTime:InvokeServer()
local function toHMS(s)
return ("%02i:%02i:%02i"):format(s/3600, s/60%60, s%60)
end
while wait(1) do
if timeleft == nil then
script.Parent.Text = "Claim"
else
script.Parent.Text = toHMS(target - os.time())
end
end
I have no clue what I’m doing wrong, or there is an error?
I think I found an easier way, I’m just going to store the timer inside a folder in the player. When I need to display it I’ll use my minutes to hours:minutes:seconds function. It seems a lot easier
Okay so this works in theory but in practice you’re gunna run into a lot of problems. Here’s the thing, os.time() and tick() are both accurate ways to measure time on instance are a time. But in reality they are NOT and accurate measure for long periods of time where a player is expected to leave and rejoin the game at some point. When a player joins again, the time value could be entirely different based on the server region they happen to connect to. The only way to really verify this perfectly across all servers is by using something called unixtime. This is essentially the same thing except the way you should go about getting it is by using apis in your game to find the real world time right away. This means diving into some HTTPService stuff.
I have done a daily reward system before, and actually it’s not that hard. What I did was I saved the previous os.time() value when the received their last reward and compared it to the current time. If the current time is greater than the saved time + (24*3600) then I would save the current time and give them the reward
Posted code if anyone searches it up in the future
local code = 'AAA' --Change to reset the daily reward thing
local DSS = game:GetService("DataStoreService")
local dailyRewardSystem = DSS:GetDataStore('dailyReward_'..code)
local hoursUntil = 24
game.Players.PlayerAdded:Connect(function(player)
local dailyRewardFolder = Instance.new("Folder",player)
dailyRewardFolder.Name = 'Rewards'
local timeUntilStuff = Instance.new("IntValue",dailyRewardFolder)
timeUntilStuff.Name = 'DailyReward'
local timeUntil
local success, err = pcall(function()
timeUntil = dailyRewardSystem:GetAsync(player.UserId) or 0
end)
if success then
timeUntilStuff.Value = timeUntil - os.time()
print((timeUntil) - os.time())
end
end)
local function checkIfCanRecieve(player)
local dr = player:FindFirstChild('Rewards'):WaitForChild('DailyReward')
if dr then
if dr.Value + os.time() < os.time() then
print('Yes')
print(os.time(),os.time()+3600*hoursUntil)
dr.Value = 3600*hoursUntil
dailyRewardSystem:SetAsync(player.UserId, os.time()+(3600*hoursUntil))
end
end
end
wait(2)
checkIfCanRecieve(game.Players:FindFirstChildOfClass("Player"))
while wait(1) do
for i,v in ipairs(game.Players:GetPlayers()) do
if v:FindFirstChild('Rewards'):FindFirstChild('DailyReward') then
v:FindFirstChild('Rewards'):FindFirstChild('DailyReward').Value = v:FindFirstChild('Rewards'):FindFirstChild('DailyReward').Value - 1
end
end
end