2025-03-04 19:31:07 +00:00
-- Copyright (C) 2025 snoutie
-- Authors: snoutie (copyright@achtarmig.org)
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero 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 Affero General Public License for more details.
-- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
local M = { }
M.dependencies = { ' career_career ' , ' career_saveSystem ' , ' career_modules_inventory ' }
local extensionName = " career_vehicleSaveSystem "
local vehicleSaves_temp = " /temp/career/vehicle_saves "
local function CreateDirectories ( dir )
local p = path.dirname ( dir )
if not FS : directoryExists ( p ) then
CreateDirectories ( string.sub ( p , 1 , # p - 1 ) )
end
FS : directoryCreate ( dir )
end
local function ClearDirectory ( dir )
local files = FS : findFiles ( dir .. " / " , ' * ' , 0 , false , true )
for i = 1 , tableSize ( files ) do
FS : remove ( files [ i ] )
end
end
local function CopySaves ( from , to )
local save_folders = FS : directoryList ( from , false , true )
for i = 1 , tableSize ( save_folders ) do
local folder_dir , folder_name , _ = path.split ( save_folders [ i ] )
FS : directoryCreate ( to .. " / " .. folder_name )
local save_files = FS : findFiles ( folder_dir .. folder_name .. " / " , ' *.json ' , 0 , false , false )
for n = 1 , tableSize ( save_files ) do
local file_dir , file_name , file_ext = path.split ( save_files [ n ] )
FS : remove ( to .. " / " .. folder_name .. " / " .. file_name )
FS : copyFile ( file_dir .. file_name , to .. " / " .. folder_name .. " / " .. file_name )
end
end
end
local function LoadFiles ( from )
ClearDirectory ( vehicleSaves_temp )
CopySaves ( from , vehicleSaves_temp )
end
local function SaveFiles ( to )
CopySaves ( vehicleSaves_temp , to )
end
local function GetVehicleSaveFile ( root , inventoryId )
local path = root .. " / " .. inventoryId
CreateDirectories ( path )
return path .. " /save.json "
end
local function QueueVehicleToSave ( inventoryId )
M.queuedVehicleSaves [ inventoryId ] = true
end
local function QueuedVehicleSaved ( inventoryId )
log ( " I " , " saving " , " saved vehicle " .. inventoryId )
table.remove ( M.queuedVehicleSaves , inventoryId )
end
local function VehiclesSaved ( )
if next ( M.queuedVehicleSaves ) == nil then
log ( ' I ' , ' saving ' , ' all vehicles saved ' )
return true
else
log ( ' I ' , ' saving ' , ' still saving vehicles ' )
end
return false
end
local function CheckSavedAsync ( callback )
extensions.core_jobsystem . create (
function ( job )
while true do
if VehiclesSaved ( ) then
break
end
job.sleep ( 0.1 )
end
if callback then
callback ( )
end
end )
end
local function SaveVehicle ( inventoryId )
local saveFile = GetVehicleSaveFile ( vehicleSaves_temp , inventoryId )
local vehicleId = career_modules_inventory.getVehicleIdFromInventoryId ( inventoryId )
if vehicleId then
log ( ' I ' , ' saving ' , ' saving vehicle ' .. inventoryId .. " to " .. saveFile )
local object = be : getObjectByID ( vehicleId )
object : queueLuaCommand ( " beamstate.save( \" " ..
saveFile ..
2025-03-05 17:29:39 +00:00
" \" ); obj:queueGameEngineLua('career_vehicleSaveSystem.QueuedVehicleSaved( \" " .. inventoryId .. " \" )'); " )
2025-03-04 19:31:07 +00:00
return true
else
return false
end
end
local function LoadVehicle ( inventoryId )
local saveFile = GetVehicleSaveFile ( vehicleSaves_temp , inventoryId )
local vehicleId = career_modules_inventory.getVehicleIdFromInventoryId ( inventoryId )
if vehicleId then
log ( " I " , " loading " , " loading vehicle from " .. saveFile )
local object = be : getObjectByID ( vehicleId )
object : queueLuaCommand ( " beamstate.load( \" " ..
2025-03-05 17:29:39 +00:00
saveFile .. " \" ); " ..
" for key, value in pairs(v.data.controller) do if value['fileName'] == 'advancedCouplerControl' then local c = controller.getController(value['name']) if c['reset'] then c['reset']() end end end "
)
2025-03-04 19:31:07 +00:00
end
end
local function onSaveCurrentSaveSlotAsyncStart ( )
career_saveSystem.registerAsyncSaveExtension ( extensionName )
end
local function onSaveCurrentSaveSlot ( currentSavePath , oldSaveDate , vehiclesThumbnailUpdate )
local vehicles = career_modules_inventory.getVehicles ( )
for id , _ in pairs ( vehicles ) do
QueueVehicleToSave ( id )
end
for id , _ in pairs ( M.queuedVehicleSaves ) do
if not SaveVehicle ( id ) then
QueuedVehicleSaved ( id )
end
end
CheckSavedAsync ( function ( )
SaveFiles ( currentSavePath .. " /career/vehicle_saves " )
career_saveSystem.asyncSaveExtensionFinished ( extensionName )
end )
end
local function onCareerActive ( )
local _ , saveSlot = career_saveSystem.getCurrentSaveSlot ( )
local vehicleSaves_saveSlot = saveSlot .. " /career/vehicle_saves "
CreateDirectories ( vehicleSaves_saveSlot )
CreateDirectories ( vehicleSaves_temp )
LoadFiles ( vehicleSaves_saveSlot )
end
M.queuedVehicleSaves = { }
M.SaveVehicle = SaveVehicle
M.LoadVehicle = LoadVehicle
M.CheckSavedAsync = CheckSavedAsync
M.QueueVehicleToSave = QueueVehicleToSave
M.QueuedVehicleSaved = QueuedVehicleSaved
M.onSaveCurrentSaveSlotAsyncStart = onSaveCurrentSaveSlotAsyncStart
M.onSaveCurrentSaveSlot = onSaveCurrentSaveSlot
M.onCareerActive = onCareerActive
return M