diff --git a/sonorancms/client/client.lua b/sonorancms/client/client.lua index 35ab5dd..700e1d3 100644 --- a/sonorancms/client/client.lua +++ b/sonorancms/client/client.lua @@ -4,6 +4,15 @@ local warningMessage = nil local secondsCount = 10 local breakOff = false local notReset = true +local CurrentWeather = 'EXTRASUNNY' +local lastWeather = CurrentWeather +local baseTime = 8 +local timeOffset = 0 +local timer = 0 +local freezeTime = false +local blackout = false +local blackoutVehicle = false + RegisterNetEvent('SonoranCMS::core::RequestGamePool', function() local returnVehicleData = {} for _, v in pairs(GetGamePool('CVehicle')) do @@ -247,6 +256,9 @@ end local deathFlag = false local IsEntityDead = IsEntityDead CreateThread(function() + local hour + local minute = 0 + local second = 0 while true do Wait(100) local ped = PlayerPedId() @@ -261,17 +273,70 @@ CreateThread(function() if IsPedShooting(playerped) then TriggerServerEvent('SonoranCMS::ServerLogger::PlayerShot', fivemfivemDeathHashTable[GetSelectedPedWeapon(playerped)]) end + if GetResourceState('qb-weathersync') ~= 'started' then + if lastWeather ~= CurrentWeather then + lastWeather = CurrentWeather + SetWeatherTypeOverTime(CurrentWeather, 15.0) + Wait(15000) + end + Wait(100) + SetArtificialLightsState(blackout) + SetArtificialLightsStateAffectsVehicles(blackoutVehicle) + ClearOverrideWeather() + ClearWeatherTypePersist() + SetWeatherTypePersist(lastWeather) + SetWeatherTypeNow(lastWeather) + SetWeatherTypeNowPersist(lastWeather) + if lastWeather == 'XMAS' then + SetForceVehicleTrails(true) + SetForcePedFootstepsTracks(true) + else + SetForceVehicleTrails(false) + SetForcePedFootstepsTracks(false) + end + if lastWeather == 'RAIN' then + SetRainLevel(0.3) + elseif lastWeather == 'THUNDER' then + SetRainLevel(0.5) + else + SetRainLevel(0.0) + end + local newBaseTime = baseTime + if GetGameTimer() - 22 > timer then + second = second + 1 + timer = GetGameTimer() + end + if freezeTime then + timeOffset = timeOffset + baseTime - newBaseTime + second = 0 + end + baseTime = newBaseTime + hour = math.floor(((baseTime + timeOffset) / 60) % 24) + if minute ~= math.floor((baseTime + timeOffset) % 60) then + minute = math.floor((baseTime + timeOffset) % 60) + second = 0 + end + NetworkOverrideClockTime(hour, minute, second) + end end end) -AddEventHandler("QBCore:Command:SpawnVehicle", function(vehicle) +AddEventHandler('QBCore:Command:SpawnVehicle', function(vehicle) TriggerServerEvent('SonoranCMS::ServerLogger::QBSpawnVehicle', vehicle) end) -AddEventHandler("QBCore:Command:DeleteVehicle", function() +AddEventHandler('QBCore:Command:DeleteVehicle', function() TriggerServerEvent('SonoranCMS::ServerLogger::QBDeleteVehicle') end) AddEventHandler('QBCore:Client:UseItem', function(item) TriggerServerEvent('SonoranCMS::ServerLogger::QBClientUsedItem', item) -end) \ No newline at end of file +end) + +RegisterNetEvent('SonoranCMS::core::SetEnvironment', function(data) + CurrentWeather = data.currentWeather + blackout = data.blackout + freezeTime = data.freezeTime + timeOffset = data.timeOffset + baseTime = data.baseTime +end) diff --git a/sonorancms/fxmanifest.lua b/sonorancms/fxmanifest.lua index 5848ac8..bc9b3fd 100644 --- a/sonorancms/fxmanifest.lua +++ b/sonorancms/fxmanifest.lua @@ -4,7 +4,7 @@ games {'gta5'} author 'Sonoran Software Systems' real_name 'Sonoran CMS FiveM Integration' description 'Sonoran CMS to FiveM translation layer' -version '1.4.0' +version '1.4.1' lua54 'yes' server_scripts {'server/*.lua', 'config.lua', 'server/util/unzip.js', 'server/util/http.js', 'server/util/sonoran.js', 'server/util/utils.js', '@oxmysql/lib/MySQL.lua', 'server/util/imageHandler.js', 'server/modules/**/*_sv.js', 'server/modules/**/*_sv.lua'} diff --git a/sonorancms/server/pushEvents.lua b/sonorancms/server/pushEvents.lua index f88fa24..2fee07d 100644 --- a/sonorancms/server/pushEvents.lua +++ b/sonorancms/server/pushEvents.lua @@ -1,6 +1,13 @@ local vehicleGamePool = {} local tonumber = tonumber local loggerBuffer = {} +local CurrentWeather = 'EXTRASUNNY' +local baseTime = 8 +local timeOffset = 0 +local freezeTime = false +local blackout = false +local newWeatherTimer = 10 +local dynamicWeather = true local explosionTypes = {'GRENADE', 'GRENADELAUNCHER', 'STICKYBOMB', 'MOLOTOV', 'ROCKET', 'TANKSHELL', 'HI_OCTANE', 'CAR', 'PLANE', 'PETROL_PUMP', 'BIKE', 'DIR_STEAM', 'DIR_FLAME', 'DIR_WATER_HYDRANT', 'DIR_GAS_CANISTER', 'BOAT', 'SHIP_DESTROY', 'TRUCK', 'BULLET', 'SMOKEGRENADELAUNCHER', 'SMOKEGRENADE', 'BZGAS', 'FLARE', 'GAS_CANISTER', 'EXTINGUISHER', 'PROGRAMMABLEAR', 'TRAIN', 'BARREL', 'PROPANE', 'BLIMP', 'DIR_FLAME_EXPLODE', 'TANKER', 'PLANE_ROCKET', 'VEHICLE_BULLET', 'GAS_TANK', 'BIRD_CRAP', 'RAILGUN', 'BLIMP2', 'FIREWORK', 'SNOWBALL', 'PROXMINE', 'VALKYRIE_CANNON', @@ -80,6 +87,51 @@ local function sortArrayBy(array, key) end end +-- CREDIT: https://github.com/qbcore-framework/qb-weathersync/blob/74dadb90b9bdfc0a7ce492a406a769fcf9c96596/server/server.lua#L42C16-L42C32 +--- Sets the next weather stage +local function nextWeatherStage() + if CurrentWeather == 'CLEAR' or CurrentWeather == 'CLOUDS' or CurrentWeather == 'EXTRASUNNY' then + CurrentWeather = (math.random(1, 5) > 2) and 'CLEARING' or 'OVERCAST' -- 60/40 chance + elseif CurrentWeather == 'CLEARING' or CurrentWeather == 'OVERCAST' then + local new = math.random(1, 6) + if new == 1 then + CurrentWeather = (CurrentWeather == 'CLEARING') and 'FOGGY' or 'RAIN' + elseif new == 2 then + CurrentWeather = 'CLOUDS' + elseif new == 3 then + CurrentWeather = 'CLEAR' + elseif new == 4 then + CurrentWeather = 'EXTRASUNNY' + elseif new == 5 then + CurrentWeather = 'SMOG' + else + CurrentWeather = 'FOGGY' + end + elseif CurrentWeather == 'THUNDER' or CurrentWeather == 'RAIN' then + CurrentWeather = 'CLEARING' + elseif CurrentWeather == 'SMOG' or CurrentWeather == 'FOGGY' then + CurrentWeather = 'CLEAR' + else + CurrentWeather = 'CLEAR' + end + local data = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, data) +end + +-- CREDIT: https://github.com/qbcore-framework/qb-weathersync/blob/74dadb90b9bdfc0a7ce492a406a769fcf9c96596/server/server.lua#L31C1-L31C1 +--- Sets time offset based on minutes provided +--- @param minute number - Minutes to offset by +local function shiftToMinute(minute) + timeOffset = timeOffset - (((baseTime + timeOffset) % 60) - minute) +end + +-- CREDIT: https://github.com/qbcore-framework/qb-weathersync/blob/74dadb90b9bdfc0a7ce492a406a769fcf9c96596/server/server.lua#L37 +--- Sets time offset based on hour provided +--- @param hour number - Hour to offset by +local function shiftToHour(hour) + timeOffset = timeOffset - ((((baseTime + timeOffset) / 60) % 24) - hour) * 60 +end + CreateThread(function() TriggerEvent('sonorancms::RegisterPushEvent', 'CMD_KICK_PLAYER', function(data) if data ~= nil then @@ -1159,6 +1211,80 @@ CreateThread(function() manuallySendPayload() end end) + TriggerEvent('sonorancms::RegisterPushEvent', 'CMD_SET_ENVIRONMENT_TIME', function(data) + if data ~= nil then + if GetResourceState('qb-weathersync') == 'started' then + TriggerEvent('qb-weathersync:server:setTime', data.data.hour, data.data.minute) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting environment time to ' .. data.data.hour .. ':' .. data.data.minute) + manuallySendPayload() + else + shiftToHour(tonumber(data.data.hour)) + shiftToMinute(tonumber(data.data.minute)) + manuallySendPayload() + local environmentData = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, environmentData) + end + end + end) + TriggerEvent('sonorancms::RegisterPushEvent', 'CMD_SET_ENVIRONMENT_WEATHER', function(data) + if data ~= nil then + if GetResourceState('qb-weathersync') == 'started' then + TriggerEvent('qb-weathersync:server:setWeather', data.data.weatherState) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting environment weather to ' .. data.data.weatherState) + manuallySendPayload() + else + CurrentWeather = data.data.weatherState + local environmentData = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, environmentData) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting environment weather to ' .. data.data.weatherState) + manuallySendPayload() + end + end + end) + TriggerEvent('sonorancms::RegisterPushEvent', 'CMD_SET_ENVIRONMENT_FREEZE_WEATHER', function(data) + if data ~= nil then + if GetResourceState('qb-weathersync') == 'started' then + TriggerEvent('qb-weathersync:server:toggleDynamicWeather', data.data.freezeWeather) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting weather freeze to ' .. json.encode(data.data.freezeWeather)) + manuallySendPayload() + else + dynamicWeather = data.data.freezeWeather + local environmentData = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, environmentData) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting weather freeze to ' .. json.encode(data.data.freezeWeather)) + manuallySendPayload() + end + end + end) + TriggerEvent('sonorancms::RegisterPushEvent', 'CMD_SET_ENVIRONMENT_FREEZE_TIME', function(data) + if data ~= nil then + if GetResourceState('qb-weathersync') == 'started' then + TriggerEvent('qb-weathersync:server:toggleFreezeTime', data.data.freezeTime) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting time freeze to ' .. json.encode(data.data.freezeTime)) + manuallySendPayload() + else + freezeTime = data.data.freezeTime + local environmentData = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, environmentData) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting time freeze to ' .. json.encode(data.data.freezeTime)) + manuallySendPayload() + end + end + end) + TriggerEvent('sonorancms::RegisterPushEvent', 'CMD_SET_ENVIRONMENT_TOGGLE_BLACKOUT', function(data) + if data ~= nil then + if GetResourceState('qb-weathersync') == 'started' then + TriggerEvent('qb-weathersync:server:toggleBlackout', data.data.blackout) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting blackout to ' .. json.encode(data.data.blackout)) + else + blackout = data.data.blackout + local environmentData = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, environmentData) + TriggerEvent('SonoranCMS::core:writeLog', 'debug', 'Received push event: ' .. data.type .. ' setting blackout to ' .. json.encode(data.data.blackout)) + manuallySendPayload() + end + end + end) end) CreateThread(function() @@ -1190,50 +1316,51 @@ function manuallySendPayload() 'sonorancms_ace_perms was started, however it is now bundled with the SonoranCMS Core, please remove the sonorancms_ace_perms resource before continuing.') table.insert(errors, {code = 'ERR_ACE_PERMS_STARTED', message = 'sonorancms_ace_perms was started, however it is now bundled with the SonoranCMS Core, please remove the sonorancms_ace_perms resource before continuing.'}) - pcall(function() + pcall(function() + if GetResourceState('sonorancms_ace_perms') == 'started' then + ExecuteCommand('stop sonorancms_ace_perms') + Wait(1000) if GetResourceState('sonorancms_ace_perms') == 'started' then - ExecuteCommand('stop sonorancms_ace_perms') - Wait(1000) - if GetResourceState('sonorancms_ace_perms') == 'started' then - TriggerEvent('SonoranCMS::core:writeLog', 'error', 'Failed to stop the old SonoranCMS sonorancms_ace_perms resource. Please remove this addon as it is now bundled with SonoranCMS.') - else - TriggerEvent('SonoranCMS::core:writeLog', 'info', 'Successfully stopped the old SonoranCMS sonorancms_ace_perms resource. Please remove this addon as it is now bundled with SonoranCMS.') - end + TriggerEvent('SonoranCMS::core:writeLog', 'error', 'Failed to stop the old SonoranCMS sonorancms_ace_perms resource. Please remove this addon as it is now bundled with SonoranCMS.') + else + TriggerEvent('SonoranCMS::core:writeLog', 'info', 'Successfully stopped the old SonoranCMS sonorancms_ace_perms resource. Please remove this addon as it is now bundled with SonoranCMS.') end - end) + end + end) end if GetResourceState('sonorancms_clockin') == 'started' then - TriggerEvent('SonoranCMS::core:writeLog', 'warn', 'sonorancms_clockin was started, however it is now bundled with the SonoranCMS Core, please remove the sonorancms_clockin resource before continuing.') + TriggerEvent('SonoranCMS::core:writeLog', 'warn', + 'sonorancms_clockin was started, however it is now bundled with the SonoranCMS Core, please remove the sonorancms_clockin resource before continuing.') table.insert(errors, {code = 'ERR_CLOCKIN_STARTED', message = 'sonorancms_clockin was started, however it is now bundled with the SonoranCMS Core, please remove the sonorancms_clockin resource before continuing.'}) - pcall(function() + pcall(function() + if GetResourceState('sonorancms_clockin') == 'started' then + ExecuteCommand('stop sonorancms_clockin') + Wait(1000) if GetResourceState('sonorancms_clockin') == 'started' then - ExecuteCommand('stop sonorancms_clockin') - Wait(1000) - if GetResourceState('sonorancms_clockin') == 'started' then - TriggerEvent('SonoranCMS::core:writeLog', 'error', 'Failed to stop the old SonoranCMS sonorancms_clockin resource. Please remove this addon as it is now bundled with SonoranCMS.') - else - TriggerEvent('SonoranCMS::core:writeLog', 'info', 'Successfully stopped the old SonoranCMS sonorancms_clockin resource. Please remove this addon as it is now bundled with SonoranCMS.') - end + TriggerEvent('SonoranCMS::core:writeLog', 'error', 'Failed to stop the old SonoranCMS sonorancms_clockin resource. Please remove this addon as it is now bundled with SonoranCMS.') + else + TriggerEvent('SonoranCMS::core:writeLog', 'info', 'Successfully stopped the old SonoranCMS sonorancms_clockin resource. Please remove this addon as it is now bundled with SonoranCMS.') end - end) + end + end) end if GetResourceState('sonorancms_whitelist') == 'started' then TriggerEvent('SonoranCMS::core:writeLog', 'warn', 'sonorancms_whitelist was started, however it is now bundled with the SonoranCMS Core, please remove the sonorancms_whitelist resource before continuing.') table.insert(errors, {code = 'ERR_ACE_PERMS_STARTED', message = 'sonorancms_whitelist was started, however it is now bundled with the SonoranCMS Core, please remove the sonorancms_whitelist resource before continuing.'}) - pcall(function() + pcall(function() + if GetResourceState('sonorancms_whitelist') == 'started' then + ExecuteCommand('stop sonorancms_whitelist') + Wait(1000) if GetResourceState('sonorancms_whitelist') == 'started' then - ExecuteCommand('stop sonorancms_whitelist') - Wait(1000) - if GetResourceState('sonorancms_whitelist') == 'started' then - TriggerEvent('SonoranCMS::core:writeLog', 'error', 'Failed to stop the old SonoranCMS sonorancms_whitelist resource. Please remove this addon as it is now bundled with SonoranCMS.') - else - TriggerEvent('SonoranCMS::core:writeLog', 'info', 'Successfully stopped the old SonoranCMS sonorancms_whitelist resource. Please remove this addon as it is now bundled with SonoranCMS.') - end + TriggerEvent('SonoranCMS::core:writeLog', 'error', 'Failed to stop the old SonoranCMS sonorancms_whitelist resource. Please remove this addon as it is now bundled with SonoranCMS.') + else + TriggerEvent('SonoranCMS::core:writeLog', 'info', 'Successfully stopped the old SonoranCMS sonorancms_whitelist resource. Please remove this addon as it is now bundled with SonoranCMS.') end - end) + end + end) end if GetResourceState('qb-core') == 'started' then if GetResourceState('qb-inventory') ~= 'started' and GetResourceState('ox_inventory') ~= 'started' and GetResourceState('qs-inventory') ~= 'started' and GetResourceState('ps-inventory') ~= 'started' then @@ -1776,3 +1903,47 @@ RegisterNetEvent('SonoranCMS::ServerLogger::QBClientUsedItem', function(item) serverLogger(source, 'QBCore:Command:ClientUsedItem', item) end) +-- CREDIT: https://github.com/qbcore-framework/qb-weathersync/blob/74dadb90b9bdfc0a7ce492a406a769fcf9c96596/server/server.lua#L282 +CreateThread(function() + local previous = 0 + while true do + Wait(0) + local newBaseTime = os.time(os.date('!*t')) / 2 + 360 -- Set the server time depending of OS time + 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 +end) + +CreateThread(function() + while true do + Wait(2000) + local data = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, data) + end +end) + +CreateThread(function() + while true do + Wait(300000) + local data = {currentWeather = CurrentWeather, blackout = blackout, freezeTime = freezeTime, timeOffset = timeOffset, baseTime = baseTime} + TriggerClientEvent('SonoranCMS::core::SetEnvironment', -1, data) + end +end) + +CreateThread(function() + while true do + newWeatherTimer = newWeatherTimer - 1 + Wait((1000 * 60) * 10) + if newWeatherTimer == 0 then + if dynamicWeather then + nextWeatherStage() + end + newWeatherTimer = 10 + end + end +end) diff --git a/sonorancms/version.json b/sonorancms/version.json index 6dea919..4956e1a 100644 --- a/sonorancms/version.json +++ b/sonorancms/version.json @@ -1,4 +1,4 @@ { - "resource": "1.4.0", + "resource": "1.4.1", "testedFxServerVersion": "5777" }