Files
fs25-adsmartpickup/FS25_ADSmartPickup/adRunsController.lua
T

637 lines
26 KiB
Lua

-- AD Runs Controller
-- Oversætter et run til AutoDrive-tilstand pr. traktor: validering, Start/Stop, status,
-- Auto-vareliste, og "hvilket run hører traktoren til". GUI'et kalder kun herind;
-- de eksisterende hooks (choosePickup, Wait-punkter) spørger getRunForVehicle/getRunIngredients.
ADRunsController = {}
ADRunsController.LOG_PREFIX = "ADSmartPickup: "
-- Længere væk fra vejnettet end dette kan AutoDrive ikke starte (samme grænse som AD's HUD).
ADRunsController.MAX_NETWORK_DISTANCE = 30
ADRunsController.store = ADRuns.newStore()
local function copyList(list)
local copy = {}
for index, value in ipairs(list or {}) do
copy[index] = value
end
return copy
end
-- Stabil nøgle: FS25's uniqueId ("vehicle…"), ellers savegame-id. Navne bruges aldrig.
function ADRunsController.getVehicleId(vehicle)
if vehicle.uniqueId ~= nil then
return tostring(vehicle.uniqueId)
end
if vehicle.getUniqueId ~= nil then
local id = vehicle:getUniqueId()
if id ~= nil then
return tostring(id)
end
end
if vehicle.currentSavegameId ~= nil then
return tostring(vehicle.currentSavegameId)
end
return nil
end
function ADRunsController.getFarmVehicles(adEnv)
local farmId = g_currentMission:getFarmId()
local result = {}
for _, vehicle in pairs(adEnv.AutoDrive.getAllVehicles()) do
-- kun motoriserede (traktorer, høstere); AD-spec'en sidder også på redskaber
local isMotorized = vehicle.spec_motorized ~= nil or vehicle.spec_motorized == nil and vehicle.startAutoDrive ~= nil
if vehicle.ad ~= nil and isMotorized and vehicle.getOwnerFarmId ~= nil and vehicle:getOwnerFarmId() == farmId then
table.insert(result, vehicle)
end
end
return result
end
-- Ét map pr. kald i stedet for at genscanne getFarmVehicles pr. vehicleId — startRun/stopRun/
-- getRunStatus/load slår flere id'er op pr. kald, og GUI'et kalder getRunStatus hvert sekund.
local function getFarmVehiclesById(adEnv)
local byId = {}
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
local id = ADRunsController.getVehicleId(vehicle)
if id ~= nil then
byId[id] = vehicle
end
end
return byId
end
function ADRunsController.findVehicleById(adEnv, vehicleId)
return getFarmVehiclesById(adEnv)[vehicleId]
end
function ADRunsController.getRunForVehicle(vehicle)
local id = ADRunsController.getVehicleId(vehicle)
return id ~= nil and ADRuns.findRunByVehicle(ADRunsController.store, id) or nil
end
-- ---- store-wrappers (erstatter altid hele store'en; modellen muterer aldrig) ----
function ADRunsController.createRun(name)
local store, run = ADRuns.createRun(ADRunsController.store, name)
ADRunsController.store = store
return run
end
function ADRunsController.deleteRun(runId, adEnv)
local run = ADRuns.getRun(ADRunsController.store, runId)
if run ~= nil and adEnv ~= nil then
for _, vehicleId in ipairs(run.vehicleIds) do
ADRunsController.stopIfRunning(ADRunsController.findVehicleById(adEnv, vehicleId), "run slettet")
end
end
ADRunsController.store = ADRuns.deleteRun(ADRunsController.store, runId)
end
-- Hver ændring logges, så et klik der ikke når modellen kan ses i log.txt.
function ADRunsController.updateRun(runId, changes)
ADRunsController.store = ADRuns.updateRun(ADRunsController.store, runId, changes)
local run = ADRuns.getRun(ADRunsController.store, runId)
local parts = {}
for key, value in pairs(changes) do
table.insert(parts, string.format("%s=%s", tostring(key), type(value) == "table" and table.concat(value, " ") or tostring(value)))
end
table.sort(parts)
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': %s", run ~= nil and tostring(run.name) or tostring(runId), table.concat(parts, ", "))
end
function ADRunsController.assignVehicle(runId, vehicle)
local id = ADRunsController.getVehicleId(vehicle)
if id == nil then
return nil
end
local store, previousRunId = ADRuns.assignVehicle(ADRunsController.store, runId, id)
ADRunsController.store = store
return previousRunId
end
function ADRunsController.unassignVehicle(vehicle)
local id = ADRunsController.getVehicleId(vehicle)
if id ~= nil then
ADRunsController.store = ADRuns.unassignVehicle(ADRunsController.store, id)
ADRunsController.stopIfRunning(vehicle, "fjernet fra run")
end
end
-- ---- varer ----
function ADRunsController.getCarriableFillTypes(adEnv, vehicle)
return adEnv.AutoDrive.getSupportedFillTypesOfAllUnitsAlphabetically(vehicle) or {}
end
-- Auto-listen: det vognen kan bære, som målet også tager. Er målet en fabrik, indsnævrer
-- findSupplyPickup selv til de ønskede produktioners inputs bagefter.
-- Run'ets mål som liste (flere stalde pr. run); gamle runs har kun targetWayPointId.
function ADRunsController.getRunTargets(run)
if run.targetWayPointIds ~= nil and #run.targetWayPointIds > 0 then
return run.targetWayPointIds
end
return run.targetWayPointId ~= nil and {run.targetWayPointId} or {}
end
local function getTargetStations(adEnv, run, farmId)
local stations = {}
for _, wayPointId in ipairs(ADRunsController.getRunTargets(run)) do
local station = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, wayPointId, farmId)
if station ~= nil then
table.insert(stations, {wayPointId = wayPointId, station = station})
end
end
return stations
end
function ADRunsController.getTargetFillTypes(adEnv, run, vehicle)
local farmId = ADSmartPickup.getFarmId(vehicle)
-- En kørende traktor følger AD's eget mål (stateModule:getSecondMarker(), det samme
-- choosePickup/findSupplyPickup bruger) indtil næste tur — IKKE run'ets gemte mål.
-- Redigerer brugeren run'ets Mål mens tildelte traktorer kører, skal Auto-listen derfor
-- følge det LIVE mål, ellers kan den blive tom og fejlagtigt smide traktoren over i
-- mappe-logikken midt i turen. Inaktiv: union over alle run'ets mål.
local stations = {}
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
if stateModule ~= nil and stateModule.isActive ~= nil and stateModule:isActive() and stateModule.getSecondMarker ~= nil then
local secondMarker = stateModule:getSecondMarker()
local station = secondMarker ~= nil and secondMarker.id ~= nil and ADSmartPickup.getUnloadStationAtWayPointId(adEnv, secondMarker.id, farmId) or nil
if station ~= nil then
stations = {{wayPointId = secondMarker.id, station = station}}
end
end
if #stations == 0 then
stations = getTargetStations(adEnv, run, farmId)
end
local result, seen = {}, {}
for _, fillType in ipairs(ADRunsController.getCarriableFillTypes(adEnv, vehicle)) do
for _, entry in ipairs(stations) do
if not seen[fillType] and ADSmartPickup.getStationLevelAndCapacity(entry.station, fillType, farmId) ~= nil then
seen[fillType] = true
table.insert(result, fillType)
end
end
end
table.sort(result)
return result
end
function ADRunsController.getRunIngredients(adEnv, run, vehicle)
if run.ingredientMode == "manual" then
local result = {}
for _, name in ipairs(run.ingredients) do
local index = g_fillTypeManager:getFillTypeIndexByName(name)
if index ~= nil then
table.insert(result, index)
end
end
return result
end
return ADRunsController.getTargetFillTypes(adEnv, run, vehicle)
end
-- Alle varer målet tager (uanset vogn) — afkrydsningslisten i GUI'et. {index, name, title}, sorteret på titel.
function ADRunsController.getTargetAcceptedFillTypes(adEnv, run)
local farmId = g_currentMission:getFarmId()
local stations = getTargetStations(adEnv, run, farmId)
if #stations == 0 then
return {}
end
local fillTypes = g_fillTypeManager.getFillTypes ~= nil and g_fillTypeManager:getFillTypes() or g_fillTypeManager.fillTypes or {}
local result = {}
for _, fillType in ipairs(fillTypes) do
if fillType.index ~= nil then
for _, entry in ipairs(stations) do
if ADSmartPickup.getStationLevelAndCapacity(entry.station, fillType.index, farmId) ~= nil then
table.insert(result, {index = fillType.index, name = fillType.name, title = fillType.title or fillType.name})
break
end
end
end
end
table.sort(result, function(a, b) return tostring(a.title) < tostring(b.title) end)
return result
end
-- Flere mål: den stald der mangler mest lige nu (bedste rangerede behov pr. mål; et FULDT
-- læs der passer vinder). nil uden mål. Ét mål = det.
function ADRunsController.chooseTarget(adEnv, run, vehicle)
local targets = ADRunsController.getRunTargets(run)
if #targets <= 1 then
return targets[1]
end
local farmId = ADSmartPickup.getFarmId(vehicle)
local ingredients = ADRunsController.getRunIngredients(adEnv, run, vehicle)
local bestId, bestNeed = nil, nil
for _, entry in ipairs(getTargetStations(adEnv, run, farmId)) do
local ranked = ADSmartPickup.getTargetNeedsRanked(entry.station, ingredients, farmId)
local need = ranked[1]
if need ~= nil and need.freeSpace >= (ADSupplyPlanner.MIN_FREE_LITERS or 1000) then
local isBetter = bestNeed == nil
or (need.fits == true and bestNeed.fits ~= true)
or (need.fits == bestNeed.fits and need.score > bestNeed.score)
if isBetter then
bestId, bestNeed = entry.wayPointId, need
end
end
end
return bestId or targets[1]
end
-- Fire traktorer kan hedde det samme; løbenummeret er pladsen i farmens AD-køretøjsliste.
function ADRunsController.getVehicleLabel(adEnv, vehicle)
for index, candidate in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
if candidate == vehicle then
return string.format("%s (#%d)", tostring(vehicle:getName()), index)
end
end
return tostring(vehicle:getName())
end
-- ---- validering ----
local function getLoadCapacity(adEnv, vehicle)
local trailers = adEnv.AutoDrive.getAllUnits(vehicle)
if trailers == nil then
return nil
end
local _, capacity = adEnv.AutoDrive.getAllFillLevels(trailers)
return capacity ~= nil and capacity > 0 and capacity or nil
end
local function intersects(listA, listB)
for _, a in ipairs(listA) do
for _, b in ipairs(listB) do
if a == b then
return true
end
end
end
return false
end
-- reason: "noTarget" | "noTrailer" | "cannotCarry" | "farFromNetwork" (l10n-nøgler i GUI'et).
function ADRunsController.validateVehicle(adEnv, run, vehicle)
local carriable = ADRunsController.getCarriableFillTypes(adEnv, vehicle)
local result = {ok = false, carriable = carriable, capacity = getLoadCapacity(adEnv, vehicle)}
local hasTarget = false
for _, wayPointId in ipairs(ADRunsController.getRunTargets(run)) do
if adEnv.ADGraphManager:getMapMarkerByWayPointId(wayPointId) ~= nil then
hasTarget = true
end
end
if not hasTarget then
result.reason = "noTarget"
return result
end
if result.capacity == nil then
result.reason = "noTrailer"
return result
end
if not intersects(ADRunsController.getRunIngredients(adEnv, run, vehicle), carriable) then
result.reason = "cannotCarry"
return result
end
-- AD's getDistanceFromNetwork kalder vehicle:getClosestWayPoint(), som ikke alle
-- AD-køretøjer har (set in-game på en høster) — uden metoden springes tjekket over.
local distance = 0
if vehicle.getClosestWayPoint ~= nil and adEnv.ADGraphManager.getDistanceFromNetwork ~= nil then
local ok, value = pcall(adEnv.ADGraphManager.getDistanceFromNetwork, adEnv.ADGraphManager, vehicle)
distance = ok and value or 0
end
if distance == nil or distance > ADRunsController.MAX_NETWORK_DISTANCE then
result.reason = "farFromNetwork"
return result
end
result.ok = true
return result
end
-- ---- Start / Stop ----
-- AD gemmer indstillinger som INDEKS i values; useFolders er global, rotateTargets pr. køretøj.
-- Er indstillingen køretøjs-specifik, men køretøjet mangler sin egen settings-tabel, skrives
-- der IKKE til den globale tabel — det ville ødelægge AD's globale default for alle køretøjer.
local function setSetting(adEnv, vehicle, settingName, value)
local global = adEnv.AutoDrive.settings[settingName]
if global == nil then
return
end
local setting = global
if global.isVehicleSpecific then
if vehicle.ad.settings == nil or vehicle.ad.settings[settingName] == nil then
return
end
setting = vehicle.ad.settings[settingName]
end
for index, candidate in ipairs(setting.values) do
if candidate == value then
setting.current = index
setting.new = index
return
end
end
end
-- Nærmeste markør med en læssestation: kun en gyldig start — moden vælger den reelle kilde pr. tur.
local function findNearestLoadMarker(adEnv, vehicle, farmId)
local x, _, z = getWorldTranslation(vehicle.rootNode)
local best, bestDistance = nil, math.huge
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
if ADSmartPickup.getLoadStationAtWayPointId(adEnv, marker.id, farmId) ~= nil then
local wayPoint = adEnv.ADGraphManager:getWayPointById(marker.id)
-- En stale markør uden waypoint skal springes over — ellers fejler Start med "error"
-- for ALLE tildelte traktorer, ikke kun den der ramte den ugyldige markør.
if wayPoint ~= nil then
local dx, dz = wayPoint.x - x, wayPoint.z - z
local distance = dx * dx + dz * dz
if distance < bestDistance then
best, bestDistance = marker, distance
end
end
end
end
return best
end
local function applyRunToVehicle(adEnv, run, vehicle, ingredients)
local stateModule = vehicle.ad.stateModule
local farmId = ADSmartPickup.getFarmId(vehicle)
stateModule:setMode(adEnv.AutoDrive.MODE_PICKUPANDDELIVER)
stateModule:setSecondMarkerByWayPointId(ADRunsController.chooseTarget(adEnv, run, vehicle) or run.targetWayPointId)
local loadMarker = findNearestLoadMarker(adEnv, vehicle, farmId)
if loadMarker ~= nil then
stateModule:setFirstMarkerByWayPointId(loadMarker.id)
end
stateModule.selectedFillTypes = copyList(ingredients)
stateModule:setFillType(ingredients[1])
stateModule.loopCounter = run.loops
stateModule:setLoopsDone(0)
setSetting(adEnv, vehicle, "useFolders", true)
setSetting(adEnv, vehicle, "rotateTargets", adEnv.AutoDrive.RT_ONLYPICKUP)
stateModule:raiseDirtyFlag()
end
local function isVehicleActive(vehicle)
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
return stateModule ~= nil and stateModule.isActive ~= nil and stateModule:isActive()
end
-- Anvend run-tilstand OG start traktoren i ét pcall'et kald: kaster vehicle:startAutoDrive()
-- (fx AD's egen validering), skal den ene traktor fejle uden at hele startRun-loopet
-- afbrydes — ellers når de øvrige tildelte traktorer aldrig at blive startet.
-- Start præcis som AD's HUD (ADInputManager:input_start_stop): det er MODE'ens start(),
-- der opretter køreopgaverne og selv kalder startAutoDrive — startAutoDrive alene sætter
-- kun "aktiv", og traktoren bliver holdende.
local function applyAndStart(adEnv, run, vehicle, ingredients)
applyRunToVehicle(adEnv, run, vehicle, ingredients)
if isVehicleActive(vehicle) then
return
end
local stateModule = vehicle.ad.stateModule
local farmId = ADSmartPickup.getFarmId(vehicle)
if stateModule.setActualFarmId ~= nil and farmId ~= nil then
stateModule:setActualFarmId(farmId)
end
stateModule:setLoopsDone(0)
local mode = stateModule.getCurrentMode ~= nil and stateModule:getCurrentMode() or nil
if mode ~= nil and mode.start ~= nil then
mode:start(adEnv.AutoDrive.USER_PLAYER or 1)
else
vehicle:startAutoDrive()
end
if vehicle.isServer and SpecializationUtil ~= nil and SpecializationUtil.raiseEvent ~= nil then
SpecializationUtil.raiseEvent(vehicle, "onUpdate", 16, false, false, false)
end
end
-- Pr. tildelt traktor: validér, skriv AD-tilstand, start. ✖-traktorer springes over.
function ADRunsController.startRun(adEnv, runId)
local run = ADRuns.getRun(ADRunsController.store, runId)
local results = {}
if run == nil then
return results
end
local vehiclesById = getFarmVehiclesById(adEnv)
for _, vehicleId in ipairs(run.vehicleIds) do
local vehicle = vehiclesById[vehicleId]
if vehicle ~= nil then
local validation = ADRunsController.validateVehicle(adEnv, run, vehicle)
local result = {vehicle = vehicle, ok = validation.ok, reason = validation.reason}
if validation.ok then
local ingredients = ADRunsController.getRunIngredients(adEnv, run, vehicle)
local ok, err = pcall(applyAndStart, adEnv, run, vehicle, ingredients)
if ok then
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' startet mod markør %s", tostring(run.name), tostring(vehicle:getName()), tostring(run.targetWayPointId))
else
result.ok, result.reason = false, "error"
Logging.warning(ADRunsController.LOG_PREFIX .. "run '%s': kunne ikke starte '%s': %s", tostring(run.name), tostring(vehicle:getName()), tostring(err))
end
end
table.insert(results, result)
end
end
return results
end
-- Som ADInputManager:input_start_stop: loops nulstilles og AD stoppes.
local function stopVehicle(vehicle)
local stateModule = vehicle.ad.stateModule
if stateModule.setLoopsDone ~= nil then
stateModule:setLoopsDone(0)
end
vehicle:stopAutoDrive()
end
-- En kørende traktor der fjernes fra sit run (eller hvis run slettes) kører run'ets job —
-- den stoppes, så den ikke fortsætter uden run. Returnerer true hvis den blev stoppet.
function ADRunsController.stopIfRunning(vehicle, reason)
if vehicle == nil or vehicle.ad == nil or not isVehicleActive(vehicle) then
return false
end
stopVehicle(vehicle)
Logging.info(ADRunsController.LOG_PREFIX .. "'%s' stoppet (%s)", tostring(vehicle:getName()), tostring(reason))
return true
end
function ADRunsController.stopRun(adEnv, runId)
local run = ADRuns.getRun(ADRunsController.store, runId)
local stopped = 0
if run == nil then
return stopped
end
local vehiclesById = getFarmVehiclesById(adEnv)
for _, vehicleId in ipairs(run.vehicleIds) do
local vehicle = vehiclesById[vehicleId]
if vehicle ~= nil and isVehicleActive(vehicle) then
stopVehicle(vehicle)
stopped = stopped + 1
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' stoppet", tostring(run.name), tostring(vehicle:getName()))
end
end
return stopped
end
function ADRunsController.getRunStatus(adEnv, run)
local running = 0
local vehiclesById = getFarmVehiclesById(adEnv)
for _, vehicleId in ipairs(run.vehicleIds) do
local vehicle = vehiclesById[vehicleId]
if vehicle ~= nil and isVehicleActive(vehicle) then
running = running + 1
end
end
return {running = running, total = #run.vehicleIds}
end
-- ---- overblik ----
-- Hvad laver traktoren lige nu? {kind = "stopped"|"waiting"|"loaded"|"empty", fillType, liters, place}
-- place = Wait-markør, aflæsningsmål eller den silo moden valgte. Kun eksisterende data bruges.
function ADRunsController.getVehicleActivity(adEnv, vehicle)
if not isVehicleActive(vehicle) then
return {kind = "stopped"}
end
local wait = ADUnloadWait ~= nil and ADUnloadWait.getWaitFor ~= nil and ADUnloadWait.getWaitFor(vehicle) or nil
if wait ~= nil then
return {kind = "waiting", fillType = wait.fillType, liters = wait.rest, place = wait.markerName}
end
local fillType, liters = nil, 0
if ADUnloadWait ~= nil and ADUnloadWait.getRestLoad ~= nil then
fillType, liters = ADUnloadWait.getRestLoad(adEnv, vehicle)
end
local stateModule = vehicle.ad.stateModule
if fillType ~= nil and liters >= 100 then
local target = stateModule.getSecondMarker ~= nil and stateModule:getSecondMarker() or nil
return {kind = "loaded", fillType = fillType, liters = liters, place = target ~= nil and target.name or nil}
end
local pickup = ADSmartPickup.getActivePickup ~= nil and ADSmartPickup.getActivePickup(vehicle) or nil
if pickup ~= nil then
return {kind = "empty", fillType = pickup.fillType, place = pickup.markerName}
end
local first = stateModule.getFirstMarker ~= nil and stateModule:getFirstMarker() or nil
return {kind = "empty", place = first ~= nil and first.name or nil}
end
-- Niveauer pr. mål for run'ets varer: {{wayPointId, name, levels = {{fillType, level, capacity, free}}}}
-- i samme rangering som valget bruger (trug som én trang, fodervægt som prioritet); fulde sidst.
function ADRunsController.getTargetsLevels(adEnv, run)
local farmId = g_currentMission:getFarmId()
local fillTypes = {}
if run.ingredientMode == "manual" then
for _, name in ipairs(run.ingredients) do
local index = g_fillTypeManager:getFillTypeIndexByName(name)
if index ~= nil then table.insert(fillTypes, index) end
end
else
for _, fillType in ipairs(ADRunsController.getTargetAcceptedFillTypes(adEnv, run)) do
table.insert(fillTypes, fillType.index)
end
end
local result = {}
for _, entry in ipairs(getTargetStations(adEnv, run, farmId)) do
local marker = adEnv.ADGraphManager:getMapMarkerByWayPointId(entry.wayPointId)
local levels = {}
for _, need in ipairs(ADSmartPickup.getTargetNeedsRanked(entry.station, fillTypes, farmId)) do
table.insert(levels, {fillType = need.fillType, level = need.level, capacity = need.capacity, free = need.freeSpace})
end
table.insert(result, {wayPointId = entry.wayPointId, name = marker ~= nil and tostring(marker.name) or tostring(entry.wayPointId), levels = levels})
end
return result
end
-- ---- opslag til dropdowns ----
-- Mål er steder der SKAL holdes fyldt: stalde (1) og fabrikker (2). Siloer tager alt og
-- er kilder, ikke mål. Returnerer markører sorteret efter type, dernæst navn.
local function getTargetKind(station)
local placeable = station.owningPlaceable
if placeable == nil then
return nil
end
if placeable.getHusbandryFillLevel ~= nil then
return 1
end
if placeable.spec_productionPoint ~= nil then
return 2
end
return nil
end
function ADRunsController.getTargetMarkers(adEnv, farmId)
local entries = {}
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
local station = ADSmartPickup.getUnloadStationAtWayPointId(adEnv, marker.id, farmId)
local kind = station ~= nil and getTargetKind(station) or nil
if kind ~= nil then
table.insert(entries, {marker = marker, kind = kind})
end
end
table.sort(entries, function(a, b)
if a.kind ~= b.kind then
return a.kind < b.kind
end
return tostring(a.marker.name) < tostring(b.marker.name)
end)
local result = {}
for index, entry in ipairs(entries) do
result[index] = entry.marker
end
return result
end
function ADRunsController.getWaitPools(adEnv)
local counts = {}
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
if ADSupplyPlanner.isWaitMarker(marker) then
counts[marker.group] = (counts[marker.group] or 0) + 1
end
end
local result = {}
for group, count in pairs(counts) do
table.insert(result, {group = group, count = count})
end
table.sort(result, function(a, b) return a.group < b.group end)
return result
end
-- ---- gem / indlæs ----
function ADRunsController.save()
local ok, saved = pcall(ADRunsStorage.save, ADRunsController.store)
if not ok then
Logging.warning(ADRunsController.LOG_PREFIX .. "kunne ikke gemme runs: %s", tostring(saved))
return false
end
return saved
end
-- Køretøjs-referencer der ikke findes (solgt, andet savegame) logges; run'et beholdes.
function ADRunsController.load(adEnv)
local ok, store = pcall(ADRunsStorage.load)
if not ok then
Logging.warning(ADRunsController.LOG_PREFIX .. "kunne ikke indlæse runs: %s", tostring(store))
return
end
ADRunsController.store = store
local vehiclesById = getFarmVehiclesById(adEnv)
for _, run in ipairs(store.runs) do
for _, vehicleId in ipairs(run.vehicleIds) do
if vehiclesById[vehicleId] == nil then
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': køretøj %s findes ikke (endnu) i dette savegame", tostring(run.name), tostring(vehicleId))
end
end
end
end
function ADRunsController.installSaveHook()
if ItemSystem == nil or ItemSystem.save == nil or Utils == nil then
return
end
ItemSystem.save = Utils.prependedFunction(ItemSystem.save, function()
ADRunsController.save()
end)
end