415 lines
		
	
	
		
			No EOL
		
	
	
		
			15 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			415 lines
		
	
	
		
			No EOL
		
	
	
		
			15 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
--[[
 | 
						|
---------------------------------------------------
 | 
						|
LUXART VEHICLE CONTROL V3 (FOR FIVEM)
 | 
						|
---------------------------------------------------
 | 
						|
Coded by Lt.Caine
 | 
						|
ELS Clicks by Faction
 | 
						|
Additional Modification by TrevorBarns
 | 
						|
---------------------------------------------------
 | 
						|
FILE: cl_storage.lua
 | 
						|
PURPOSE: Handle save/load functions and version 
 | 
						|
		 checking
 | 
						|
---------------------------------------------------
 | 
						|
This program is free software: you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation, either version 3 of the License, or
 | 
						|
(at your option) any later version.
 | 
						|
 | 
						|
This program is distributed in the hope that it will be useful,
 | 
						|
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
GNU General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
---------------------------------------------------
 | 
						|
]]
 | 
						|
STORAGE = { }
 | 
						|
 | 
						|
local save_prefix = 'lvc_'..community_id..'_'
 | 
						|
local repo_version = nil
 | 
						|
local backup_tone_table = {}
 | 
						|
local custom_tone_names = false
 | 
						|
local SIRENS_backup_string = nil
 | 
						|
local profiles = { }
 | 
						|
 | 
						|
--	forward local fn declaration
 | 
						|
local IsNewerVersion
 | 
						|
 
 | 
						|
------------------------------------------------
 | 
						|
--Deletes all saved KVPs for that vehicle profile
 | 
						|
--	This should never be removed. It is the only easy way for end users to delete LVC data.
 | 
						|
RegisterCommand('lvcfactoryreset', function(source, args)
 | 
						|
	local choice = HUD:FrontEndAlert(Lang:t('warning.warning'), Lang:t('warning.factory_reset'), Lang:t('warning.facory_reset_options'))
 | 
						|
	if choice then
 | 
						|
		STORAGE:FactoryReset()
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
function STORAGE:FactoryReset()
 | 
						|
	STORAGE:DeleteKVPs(save_prefix)
 | 
						|
	STORAGE:ResetSettings()
 | 
						|
	UTIL:Print(Lang:t('info.factory_reset_success_console'), true)
 | 
						|
	HUD:ShowNotification(Lang:t('info.factory_reset_success_frontend'), true)
 | 
						|
end
 | 
						|
 | 
						|
--Prints all KVP keys and values to console
 | 
						|
--if GetResourceMetadata(GetCurrentResourceName(), 'debug_mode', 0) == 'true' then
 | 
						|
	RegisterCommand('lvcdumpkvp', function(source, args)
 | 
						|
		UTIL:Print('^4LVC ^5STORAGE: ^7Dumping KVPs...')
 | 
						|
		local handle = StartFindKvp(save_prefix);
 | 
						|
		local key = FindKvp(handle)
 | 
						|
		while key ~= nil do
 | 
						|
			if GetResourceKvpString(key) ~= nil then
 | 
						|
				UTIL:Print('^4LVC ^5STORAGE Found: ^7"'..key..'" "'..GetResourceKvpString(key)..'", STRING', true)
 | 
						|
			elseif GetResourceKvpInt(key) ~= nil then
 | 
						|
				UTIL:Print('^4LVC ^5STORAGE Found: ^7"'..key..'" "'..GetResourceKvpInt(key)..'", INT', true)
 | 
						|
			elseif GetResourceKvpFloat(key) ~= nil then
 | 
						|
				UTIL:Print('^4LVC ^5STORAGE Found: ^7"'..key..'" "'..GetResourceKvpFloat(key)..'", FLOAT', true)
 | 
						|
			end
 | 
						|
			key = FindKvp(handle)
 | 
						|
			Wait(0)
 | 
						|
		end
 | 
						|
		UTIL:Print('^4LVC ^5STORAGE: ^7Finished Dumping KVPs...')
 | 
						|
	end)
 | 
						|
--end
 | 
						|
------------------------------------------------
 | 
						|
-- Resource Start Initialization
 | 
						|
CreateThread(function()
 | 
						|
	TriggerServerEvent('lvc:GetRepoVersion_s')
 | 
						|
	STORAGE:FindSavedProfiles()
 | 
						|
end)
 | 
						|
 | 
						|
--[[Function for Deleting KVPs]]
 | 
						|
function STORAGE:DeleteKVPs(prefix)
 | 
						|
	local handle = StartFindKvp(prefix);
 | 
						|
	local key = FindKvp(handle)
 | 
						|
	while key ~= nil do
 | 
						|
		DeleteResourceKvp(key)
 | 
						|
		UTIL:Print('^3LVC Info: Deleting Key \'' .. key .. '\'', true)
 | 
						|
		key = FindKvp(handle)
 | 
						|
		Wait(0)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
--[[Getter for current version used in RageUI.]]
 | 
						|
function STORAGE:GetCurrentVersion()
 | 
						|
	local curr_version = GetResourceMetadata(GetCurrentResourceName(), 'version', 0)
 | 
						|
	if curr_version ~= nil then
 | 
						|
		return curr_version
 | 
						|
	else
 | 
						|
		return 'unknown'
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
--[[Getter for repo version used in RageUI.]]
 | 
						|
function STORAGE:GetRepoVersion()
 | 
						|
	return repo_version
 | 
						|
end
 | 
						|
 | 
						|
--[[Getter for out-of-date notification for RageUI.]]
 | 
						|
function STORAGE:GetIsNewerVersion()
 | 
						|
	return IsNewerVersion(repo_version, STORAGE:GetCurrentVersion())
 | 
						|
end
 | 
						|
 | 
						|
--[[Saves HUD settings, separated from SaveSettings]]
 | 
						|
function STORAGE:SaveHUDSettings()
 | 
						|
	local hud_save_data = { Show_HUD = HUD:GetHudState(),
 | 
						|
							HUD_Scale = HUD:GetHudScale(), 
 | 
						|
							HUD_pos = HUD:GetHudPosition(),
 | 
						|
							HUD_backlight_mode = HUD:GetHudBacklightMode(),
 | 
						|
						  }
 | 
						|
	SetResourceKvp(save_prefix .. 'hud_data',  json.encode(hud_save_data))
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
--[[Saves all KVP values.]]
 | 
						|
function STORAGE:SaveSettings()
 | 
						|
	UTIL:Print('^4LVC: ^5STORAGE: ^7Saving Settings...')
 | 
						|
	SetResourceKvp(save_prefix..'save_version', STORAGE:GetCurrentVersion())
 | 
						|
 | 
						|
	--HUD Settings
 | 
						|
	STORAGE:SaveHUDSettings()
 | 
						|
	
 | 
						|
	--Tone Names
 | 
						|
	if custom_tone_names then
 | 
						|
		local tone_names = { }
 | 
						|
		for i, siren_pkg in pairs(SIRENS) do
 | 
						|
			table.insert(tone_names, siren_pkg.Name)
 | 
						|
		end
 | 
						|
		SetResourceKvp(save_prefix .. 'tone_names', json.encode(tone_names))
 | 
						|
		UTIL:Print('^4LVC ^5STORAGE: ^7saving '..save_prefix..'tone_names...')		
 | 
						|
	end
 | 
						|
	
 | 
						|
	--Profile Specific Settings
 | 
						|
	if UTIL:GetVehicleProfileName() ~= nil then
 | 
						|
		local profile_name = string.gsub(UTIL:GetVehicleProfileName(), ' ', '_')
 | 
						|
		if profile_name ~= nil then
 | 
						|
			local tone_options_encoded = json.encode(UTIL:GetToneOptionsTable())
 | 
						|
			local profile_save_data = {  PMANU 				= UTIL:GetToneID('PMANU'), 
 | 
						|
										 SMANU 				= UTIL:GetToneID('SMANU'),
 | 
						|
										 AUX   				= UTIL:GetToneID('AUX'),
 | 
						|
										 airhorn_intrp 		= tone_airhorn_intrp,
 | 
						|
										 main_reset_standby = tone_main_reset_standby,
 | 
						|
										 park_kill 			= park_kill,
 | 
						|
										 tone_options 		= tone_options_encoded,															  
 | 
						|
									   }
 | 
						|
							
 | 
						|
			SetResourceKvp(save_prefix .. 'profile_'..profile_name..'!',  json.encode(profile_save_data))
 | 
						|
			UTIL:Print('^4LVC ^5STORAGE: ^7saving '..save_prefix .. 'profile_'..profile_name..'!')
 | 
						|
 | 
						|
			--Audio Settings
 | 
						|
			local audio_save_data = {	
 | 
						|
										radio_masterswitch			= AUDIO.radio_masterswitch,				
 | 
						|
										button_sfx_scheme 			= AUDIO.button_sfx_scheme,
 | 
						|
										on_volume 					= AUDIO.on_volume,
 | 
						|
										off_volume 					= AUDIO.off_volume,
 | 
						|
										upgrade_volume 				= AUDIO.upgrade_volume,
 | 
						|
										downgrade_volume 			= AUDIO.downgrade_volume,
 | 
						|
										activity_reminder_volume 	= AUDIO.activity_reminder_volume,
 | 
						|
										hazards_volume 				= AUDIO.hazards_volume,
 | 
						|
										lock_volume 				= AUDIO.lock_volume,
 | 
						|
										lock_reminder_volume 		= AUDIO.lock_reminder_volume,
 | 
						|
										airhorn_button_SFX 			= AUDIO.airhorn_button_SFX,
 | 
						|
										manu_button_SFX 			= AUDIO.manu_button_SFX,
 | 
						|
										activity_reminder_index 	= AUDIO:GetActivityReminderIndex(),	
 | 
						|
									}						
 | 
						|
			SetResourceKvp(save_prefix..'profile_'..profile_name..'_audio_data',  json.encode(audio_save_data))
 | 
						|
			UTIL:Print('^4LVC ^5STORAGE: ^7saving profile_'..profile_name..'_audio_data')
 | 
						|
		else
 | 
						|
			HUD:ShowNotification('~b~LVC: ~r~SAVE ERROR~s~: profile_name after gsub is nil.', true)
 | 
						|
		end
 | 
						|
	else
 | 
						|
		HUD:ShowNotification('~b~LVC: ~r~SAVE ERROR~s~: UTIL:GetVehicleProfileName() returned nil.', true)
 | 
						|
	end
 | 
						|
	UTIL:Print('^4LVC ^5STORAGE: ^7Finished Saving Settings...')
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------
 | 
						|
--[[Loads all KVP values.]]
 | 
						|
function STORAGE:LoadSettings(profile_name)	
 | 
						|
	UTIL:Print('^4LVC ^5STORAGE: ^7Loading Settings...')
 | 
						|
	local comp_version = GetResourceMetadata(GetCurrentResourceName(), 'compatible', 0)
 | 
						|
	local save_version = GetResourceKvpString(save_prefix .. 'save_version')
 | 
						|
	local incompatible = IsNewerVersion(comp_version, save_version) == 'older'
 | 
						|
 | 
						|
	--Is save present if so what version
 | 
						|
	if incompatible then
 | 
						|
		AddTextEntry('lvc_mismatch_version','~y~~h~Warning:~h~ ~s~Luxart Vehicle Control Save Version Mismatch.\n~b~Compatible Version: ' .. comp_version .. '\n~o~Save Version: ' .. save_version .. '~s~\nYou may experience issues, to prevent this message from appearing verify settings and resave.')
 | 
						|
		SetNotificationTextEntry('lvc_mismatch_version')
 | 
						|
		DrawNotification(false, true)
 | 
						|
	end
 | 
						|
	
 | 
						|
	local hud_save_data = GetResourceKvpString(save_prefix..'hud_data')
 | 
						|
	if hud_save_data ~= nil then
 | 
						|
		hud_save_data = json.decode(hud_save_data)
 | 
						|
		HUD:SetHudState(hud_save_data.Show_HUD)
 | 
						|
		HUD:SetHudScale(hud_save_data.HUD_Scale)
 | 
						|
		HUD:SetHudPosition(hud_save_data.HUD_pos)
 | 
						|
		HUD:SetHudBacklightMode(hud_save_data.HUD_backlight_mode)
 | 
						|
		UTIL:Print('^4LVC ^5STORAGE: ^7loaded HUD data.')		
 | 
						|
	end
 | 
						|
	
 | 
						|
	if save_version ~= nil then
 | 
						|
		--Tone Names
 | 
						|
		if main_siren_settings_masterswitch then
 | 
						|
			local tone_names = GetResourceKvpString(save_prefix..'tone_names')
 | 
						|
			if tone_names ~= nil then
 | 
						|
				tone_names = json.decode(tone_names)
 | 
						|
				for i, name in pairs(tone_names) do
 | 
						|
					if SIRENS[i] ~= nil then
 | 
						|
						SIRENS[i].Name = name
 | 
						|
					end
 | 
						|
				end
 | 
						|
			end
 | 
						|
			UTIL:Print('^4LVC ^5STORAGE: ^7loaded custom tone names.')
 | 
						|
		end
 | 
						|
		
 | 
						|
		--Profile Specific Settings
 | 
						|
		if UTIL:GetVehicleProfileName() ~= false then
 | 
						|
			local profile_name = profile_name or string.gsub(UTIL:GetVehicleProfileName(), ' ', '_')	
 | 
						|
			if profile_name ~= nil then
 | 
						|
				local profile_save_data = GetResourceKvpString(save_prefix..'profile_'..profile_name..'!')
 | 
						|
				if profile_save_data ~= nil then
 | 
						|
					profile_save_data = json.decode(profile_save_data)
 | 
						|
					UTIL:SetToneByID('PMANU', profile_save_data.PMANU)
 | 
						|
					UTIL:SetToneByID('SMANU', profile_save_data.SMANU)
 | 
						|
					UTIL:SetToneByID('AUX', profile_save_data.AUX)
 | 
						|
					if main_siren_settings_masterswitch then
 | 
						|
						tone_airhorn_intrp 		= profile_save_data.airhorn_intrp
 | 
						|
						tone_main_reset_standby = profile_save_data.main_reset_standby
 | 
						|
						park_kill 				= profile_save_data.park_kill
 | 
						|
						local tone_options = json.decode(profile_save_data.tone_options)
 | 
						|
							if tone_options ~= nil then
 | 
						|
								for tone_id, option in pairs(tone_options) do
 | 
						|
									tone_id = tonumber(tone_id)
 | 
						|
									option = tonumber(option)
 | 
						|
									if SIRENS[tone_id] ~= nil then
 | 
						|
										UTIL:SetToneOption(tone_id, option)
 | 
						|
									end
 | 
						|
								end
 | 
						|
							end
 | 
						|
					end
 | 
						|
					UTIL:Print('^4LVC ^5STORAGE: ^7loaded '..profile_name..'.')
 | 
						|
				end
 | 
						|
				--Audio Settings 
 | 
						|
				local audio_save_data = GetResourceKvpString(save_prefix..'profile_'..profile_name..'_audio_data')
 | 
						|
				if audio_save_data ~= nil then
 | 
						|
					audio_save_data = json.decode(audio_save_data)
 | 
						|
					if audio_save_data.radio_masterswitch ~= nil then
 | 
						|
						AUDIO.radio_masterswitch			= audio_save_data.radio_masterswitch
 | 
						|
					end
 | 
						|
					AUDIO.button_sfx_scheme 		= audio_save_data.button_sfx_scheme
 | 
						|
					AUDIO.on_volume 				= audio_save_data.on_volume
 | 
						|
					AUDIO.off_volume 				= audio_save_data.off_volume
 | 
						|
					AUDIO.upgrade_volume 			= audio_save_data.upgrade_volume
 | 
						|
					AUDIO.downgrade_volume 			= audio_save_data.downgrade_volume
 | 
						|
					AUDIO.activity_reminder_volume 	= audio_save_data.activity_reminder_volume
 | 
						|
					AUDIO.hazards_volume 			= audio_save_data.hazards_volume
 | 
						|
					AUDIO.lock_volume 				= audio_save_data.lock_volume
 | 
						|
					AUDIO.lock_reminder_volume 		= audio_save_data.lock_reminder_volume
 | 
						|
					AUDIO.airhorn_button_SFX 		= audio_save_data.airhorn_button_SFX
 | 
						|
					AUDIO.manu_button_SFX 			= audio_save_data.manu_button_SFX
 | 
						|
					AUDIO:SetActivityReminderIndex(audio_save_data.activity_reminder_index)
 | 
						|
					UTIL:Print('^4LVC ^5STORAGE: ^7loaded audio data.')
 | 
						|
				end
 | 
						|
			else
 | 
						|
				HUD:ShowNotification('~b~LVC:~r~ LOADING ERROR~s~: profile_name after gsub is nil.', true)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	UTIL:Print('^4LVC ^5STORAGE: ^7Finished Loading Settings...')
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------
 | 
						|
--[[Resets all KVP/menu values to their default.]]
 | 
						|
function STORAGE:ResetSettings()
 | 
						|
	UTIL:Print('^4LVC ^5STORAGE: ^7Resetting Settings...')
 | 
						|
 | 
						|
	--Storage State
 | 
						|
	custom_tone_names 		= false
 | 
						|
	profiles = { }
 | 
						|
	STORAGE:FindSavedProfiles()
 | 
						|
 | 
						|
	--LVC State
 | 
						|
	key_lock 				= false				
 | 
						|
	tone_main_reset_standby = reset_to_standby_default
 | 
						|
	tone_airhorn_intrp 		= airhorn_interrupt_default
 | 
						|
	park_kill 				= park_kill_default
 | 
						|
 | 
						|
	--HUD State
 | 
						|
	HUD:SetHudState(hud_first_default)
 | 
						|
	HUD:SetHudScale(0.7)
 | 
						|
	HUD:ResetPosition()
 | 
						|
	HUD:SetHudBacklightMode(1)
 | 
						|
	
 | 
						|
	--Extra Tone Resets
 | 
						|
	UTIL:SetToneByPos('ARHRN', 1)
 | 
						|
	UTIL:SetToneByPos('PMANU', 2)
 | 
						|
	UTIL:SetToneByPos('SMANU', 3)
 | 
						|
	UTIL:SetToneByPos('AUX', 2)
 | 
						|
	UTIL:SetToneByPos('MAIN_MEM', 2)
 | 
						|
 | 
						|
	STORAGE:RestoreBackupTable()
 | 
						|
	UTIL:BuildToneOptions()
 | 
						|
	
 | 
						|
	--Audio Settings
 | 
						|
	AUDIO.radio_masterswitch 		= true
 | 
						|
	AUDIO.airhorn_button_SFX 		= false
 | 
						|
	AUDIO.manu_button_SFX 			= false
 | 
						|
	AUDIO:SetActivityReminderIndex(1)
 | 
						|
 | 
						|
	AUDIO.button_sfx_scheme 		= default_sfx_scheme_name
 | 
						|
	AUDIO.on_volume 				= default_on_volume	
 | 
						|
	AUDIO.off_volume 				= default_off_volume	
 | 
						|
	AUDIO.upgrade_volume 			= default_upgrade_volume	
 | 
						|
	AUDIO.downgrade_volume 			= default_downgrade_volume
 | 
						|
	AUDIO.hazards_volume 			= default_hazards_volume
 | 
						|
	AUDIO.lock_volume 				= default_lock_volume
 | 
						|
	AUDIO.lock_reminder_volume 		= default_lock_reminder_volume
 | 
						|
	AUDIO.activity_reminder_volume 	= default_reminder_volume
 | 
						|
	UTIL:Print('^4LVC ^5STORAGE: ^7Finished Resetting Settings...')
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------
 | 
						|
--[[Find all profile names of all saved KVP.]]
 | 
						|
function STORAGE:FindSavedProfiles()
 | 
						|
	local handle = StartFindKvp(save_prefix..'profile_');
 | 
						|
	local key = FindKvp(handle)
 | 
						|
	while key ~= nil do
 | 
						|
		if string.match(key, '(.*)!$') then
 | 
						|
			local saved_profile_name = string.match(key, save_prefix..'profile_(.*)!$')
 | 
						|
			
 | 
						|
			--Duplicate checking
 | 
						|
			local found = false
 | 
						|
			for _, profile_name in ipairs(profiles) do
 | 
						|
				if profile_name == saved_profile_name then
 | 
						|
					found = true
 | 
						|
				end
 | 
						|
			end
 | 
						|
			
 | 
						|
			if not found then
 | 
						|
				table.insert(profiles, saved_profile_name)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		key = FindKvp(handle)
 | 
						|
		Wait(0)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
function STORAGE:GetSavedProfiles()
 | 
						|
	local cur_profile = UTIL:GetVehicleProfileName()
 | 
						|
	for i, profile in ipairs(profiles) do
 | 
						|
		if profile == cur_profile then
 | 
						|
			table.remove(profiles, i)
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	return profiles
 | 
						|
end
 | 
						|
------------------------------------------------
 | 
						|
--[[Setter for JSON string backup of SIRENS table in case of reset since we modify SIREN table directly.]]
 | 
						|
function STORAGE:SetBackupTable()
 | 
						|
	SIRENS_backup_string = json.encode(SIRENS)
 | 
						|
end
 | 
						|
 | 
						|
--[[Setter for SIRENS table using backup string of table.]]
 | 
						|
function STORAGE:RestoreBackupTable()
 | 
						|
	SIRENS = json.decode(SIRENS_backup_string)
 | 
						|
end
 | 
						|
 | 
						|
--[[Setter for bool that is used in saving to determine if tone strings have been modified.]]
 | 
						|
function STORAGE:SetCustomToneStrings(toggle)
 | 
						|
	custom_tone_names = toggle
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------
 | 
						|
--HELPER FUNCTIONS for main siren settings saving:end
 | 
						|
--Compare Version Strings: Is version newer than test_version
 | 
						|
IsNewerVersion = function(version, test_version)
 | 
						|
	if version == nil or test_version == nil then
 | 
						|
		return 'unknown'
 | 
						|
	end
 | 
						|
 | 
						|
	if type(version) == 'string' then
 | 
						|
		version = semver(version)
 | 
						|
	end
 | 
						|
	if type(test_version) == 'string' then
 | 
						|
		test_version = semver(test_version)
 | 
						|
	end
 | 
						|
 | 
						|
	if version > test_version then
 | 
						|
		return 'older'
 | 
						|
	elseif version < test_version then
 | 
						|
		return 'newer'
 | 
						|
	elseif version == test_version then
 | 
						|
		return 'equal'
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
--[[Callback for Server -> Client version update.]]
 | 
						|
RegisterNetEvent('lvc:SendRepoVersion_c')
 | 
						|
AddEventHandler('lvc:SendRepoVersion_c', function(version)
 | 
						|
	repo_version = version
 | 
						|
end) |