Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fxmanifest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ game 'gta5'
lua54 'yes'
author 'Kakarot'
description 'Syncs the time & weather for all players on the server and allows editing by command'
version '2.1.0'
version '2.1.1'

shared_scripts {
'config.lua',
Expand Down
62 changes: 62 additions & 0 deletions locales/ua.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
local Translations = {
weather = {
now_frozen = 'Погода заморожена.',
now_unfrozen = 'Погода більше не заморожена.',
invalid_syntax = 'Невірний синтаксис, правильний: /weather <типпогоди> ',
invalid_syntaxc = 'Невірний синтаксис, використай /weather <типпогоди>!',
updated = 'Погода оновлена.',
invalid = 'Невірний тип погоди. Доступні типи: \nEXTRASUNNY CLEAR NEUTRAL SMOG FOGGY OVERCAST CLOUDS CLEARING RAIN THUNDER SNOW BLIZZARD SNOWLIGHT XMAS HALLOWEEN',
invalidc = 'Невірний тип погоди. Доступні типи: \nEXTRASUNNY CLEAR NEUTRAL SMOG FOGGY OVERCAST CLOUDS CLEARING RAIN THUNDER SNOW BLIZZARD SNOWLIGHT XMAS HALLOWEEN',
willchangeto = 'Погода зміниться на: %{value}.',
accessdenied = 'Доступ до команди /weather заборонено.',
},
dynamic_weather = {
disabled = 'Динамічна зміна погоди вимкнена.',
enabled = 'Динамічна зміна погоди увімкнена.',
},
time = {
frozenc = 'Час заморожено.',
unfrozenc = 'Час більше не заморожено.',
now_frozen = 'Час заморожено.',
now_unfrozen = 'Час більше не заморожено.',
morning = 'Час встановлено на ранок.',
noon = 'Час встановлено на полудень.',
evening = 'Час встановлено на вечір.',
night = 'Час встановлено на ніч.',
change = 'Час змінено на %{value}:%{value2}.',
changec = 'Час змінено на: %{value}!',
invalid = 'Невірний синтаксис. Правильний: time <година> <хвилина> !',
invalidc = 'Невірний синтаксис. Використай /time <година> <хвилина>!',
access = 'Доступ до команди /time заборонено.',
},
blackout = {
enabled = 'Режим блекауту увімкнено.',
enabledc = 'Режим блекауту увімкнено.',
disabled = 'Режим блекауту вимкнено.',
disabledc = 'Режим блекауту вимкнено.',
},
help = {
weathercommand = 'Змінити погоду.',
weathertype = 'типпогоди',
availableweather = 'Доступні типи: extrasunny, clear, neutral, smog, foggy, overcast, clouds, clearing, rain, thunder, snow, blizzard, snowlight, xmas та halloween',
timecommand = 'Змінити час.',
timehname = 'години',
timemname = 'хвилини',
timeh = 'Число від 0 до 23',
timem = 'Число від 0 до 59',
freezecommand = 'Заморозити / розморозити час.',
freezeweathercommand = 'Увімкнути/вимкнути динамічну зміну погоди.',
morningcommand = 'Встановити час на 09:00',
nooncommand = 'Встановити час на 12:00',
eveningcommand = 'Встановити час на 18:00',
nightcommand = 'Встановити час на 23:00',
blackoutcommand = 'Увімкнути/вимкнути режим блекауту.',
},
}

if GetConvar('qb_locale', 'en') == 'ua' then
Lang = Lang or Locale:new({
phrases = Translations,
warnOnMissing = true
})
end
56 changes: 21 additions & 35 deletions server/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,22 @@ local function setDynamicWeather(state)
return Config.DynamicWeather
end

--- Retrieves the current time from worldtimeapi.org
--- @return number - Unix time
--- Retrieves the current time from api.timezonedb.com
local function retrieveTimeFromApi(callback)
Citizen.CreateThread(function()
PerformHttpRequest("http://worldtimeapi.org/api/ip", function(statusCode, response)
if statusCode == 200 then
local apiKey = "REPLACE_ME_TO_YOUR_API" -- 🔐 Replace with your actual key from your email
local zone = "America/Los_Angeles" -- 🔐 Replace with your actual TimeZone, ex: America/Los_Angeles
local url = "http://api.timezonedb.com/v2.1/get-time-zone?key=" .. apiKey .. "&format=json&by=zone&zone=" .. zone
-- print(response) -- 🛠️ Debug: uncomment to inspect raw API response
PerformHttpRequest(url, function(statusCode, response)
if statusCode == 200 and response then
local data = json.decode(response)
if data == nil or data.unixtime == nil then
callback(nil)
else
callback(data.unixtime)
if data and data.timestamp then
callback(data.timestamp)
return
end
else
callback(nil)
end
callback(nil)
end, "GET", nil, nil)
end)
end
Expand Down Expand Up @@ -283,34 +284,19 @@ CreateThread(function()
local failedCount = 0

while true do
Wait(0)
Wait(60000) -- ⏱️ Sync server time every 1 minute with real time API. Falls back to OS time if failed.
local newBaseTime = os.time(os.date("!*t")) / 2 + 360 --Set the server time depending of OS time
if Config.RealTimeSync then
newBaseTime = os.time(os.date("!*t")) --Set the server time depending of OS time
if realTimeFromApi == nil then
retrieveTimeFromApi(function(unixTime)
realTimeFromApi = unixTime -- Set the server time depending on real-time retrieved from API
end)
end
while realTimeFromApi == nil do
if failedCount > 10 then
print("Failed to retrieve real time from API, falling back to local time")
break
retrieveTimeFromApi(function(unixTime)
if unixTime then
baseTime = unixTime
else
baseTime = os.time(os.date("!*t"))
end
failedCount = failedCount + 1
Wait(100)
end
if realTimeFromApi ~= nil then
newBaseTime = realTimeFromApi
end
end
if (newBaseTime % 60) ~= previous then --Check if a new minute is passed
previous = newBaseTime % 60 --Only update time with plain minutes, seconds are handled in the client
if freezeTime then
timeOffset = timeOffset + baseTime - newBaseTime
end
baseTime = newBaseTime
end
end)
else
baseTime = os.time(os.date("!*t")) / 2 + 360
end
end
end)

Expand Down
Loading