diff --git a/FS25_ADSmartPickup/adFlowWagons.lua b/FS25_ADSmartPickup/adFlowWagons.lua index b209d18..3a54fb2 100644 --- a/FS25_ADSmartPickup/adFlowWagons.lua +++ b/FS25_ADSmartPickup/adFlowWagons.lua @@ -44,6 +44,19 @@ function ADFlowWagons.startAfterManualAttach(s) return s.flowRunning == true and s.ownWagon == true and not s.adActive end +-- Husk vognen bag traktoren ved hjemtur? Kun når et KØRENDE flow stoppes (reason "stop") — ved oprydning efter +-- indlæsning ("afterLoad") kan traktoren have et puljeredskab på fra et lån (in-game 29/9). +function ADFlowWagons.shouldRememberOnHome(reason) + return reason == "stop" +end + +-- Påkobling uden ejer (hentet før genindlæsning, markopgaven tabt): s = {owned, idleMs} -> "home"|"wait"|"none" +ADFlowWagons.ORPHAN_MS = 120000 +function ADFlowWagons.orphanAction(s) + if s.owned then return "none" end + return (s.idleMs or 0) >= ADFlowWagons.ORPHAN_MS and "home" or "wait" +end + -- Hvorfor "wait" (til loggen). s som startAction. function ADFlowWagons.waitReason(s) if s.tractorBusy then return "tractorBusy" end @@ -147,6 +160,7 @@ local emptying = setmetatable({}, {__mode = "k"}) -- traktor -> {stage, since, f local homing = setmetatable({}, {__mode = "k"}) -- traktor -> true (flowets hjemtur: vogn af, traktor hjem) local fetchRetries = setmetatable({}, {__mode = "k"}) -- traktor -> antal nye hente-forsøg local lastWaitText = setmetatable({}, {__mode = "k"}) -- traktor -> sidst loggede venteårsag (kun ændringer logges) +local orphans = setmetatable({}, {__mode = "k"}) -- traktor -> ms siden påkobling uden ejer local missingCount = {} -- runId -> tjek i træk local seenBuildings = {} -- bygnings-id'er set i denne session local rememberTimer, buildingTimer = 0, 0 @@ -421,9 +435,12 @@ local function rememberWagonOf(vehicle) end -- Én traktor hjem (fra et stoppet/slettet flow): tøm først, så parkering. -function ADFlowWagons.homeVehicle(adEnv, vehicle, runName) +-- reason: "stop" (et kørende flow stoppes: vognen huskes) | "afterLoad" (oprydning: intet huskes) +function ADFlowWagons.homeVehicle(adEnv, vehicle, runName, reason) waiting[vehicle] = nil - rememberWagonOf(vehicle) -- vognen sættes af nu: flowet skal kunne finde den igen ved næste start + if ADFlowWagons.shouldRememberOnHome(reason or "stop") then + rememberWagonOf(vehicle) -- vognen sættes af nu: flowet skal kunne finde den igen ved næste start + end ADHitch.stow(vehicle, "flowet stoppet") if fetching[vehicle] ~= nil then fetching[vehicle] = nil @@ -452,6 +469,7 @@ end -- ADHitch: spilleren har selv kørt traktoren til Connect og koblet på. function ADFlowWagons.onManualAttach(adEnv, vehicle, wagon) local run = ADRunsController.getRunForVehicle(vehicle) + orphans[vehicle] = 0 -- ryddes af tickOrphans når nogen ejer opgaven (flow, markopgave, AD, spilleren) if run == nil then return end local tractorId = ADRunsController.getVehicleId(vehicle) local wagonId = wagon ~= nil and ADRunsController.getVehicleId(wagon) or nil @@ -461,11 +479,34 @@ function ADFlowWagons.onManualAttach(adEnv, vehicle, wagon) if not ADFlowWagons.startAfterManualAttach({flowRunning = not run.stopped, ownWagon = wagonId ~= nil and (remembered == nil or remembered == wagonId), adActive = module ~= nil and module:isActive()}) then return end - fetchRetries[vehicle], waiting[vehicle] = nil, nil + fetchRetries[vehicle], waiting[vehicle], orphans[vehicle] = nil, nil, nil Logging.info(ADFlowWagons.LOG_PREFIX .. "flow '%s': '%s' har selv hentet sin vogn — startes", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle))) ADRunsController.startVehicle(adEnv, run, vehicle) end +-- Traktorer der har koblet et redskab på uden ejer: efter ORPHAN_MS sættes redskabet tilbage og traktoren kører hjem. +local function tickOrphans(adEnv, elapsed) + for vehicle, idle in pairs(orphans) do + local id = ADRunsController.getVehicleId(vehicle) + local run = ADRunsController.getRunForVehicle(vehicle) + local module = vehicle.ad ~= nil and vehicle.ad.stateModule or nil + local owned = (module ~= nil and module:isActive()) or (vehicle.getIsControlled ~= nil and vehicle:getIsControlled()) + or (run ~= nil and not run.stopped) or (ADFieldJobs ~= nil and id ~= nil and ADFieldJobs.state.assignments[id] ~= nil) + or (ADCpBridge ~= nil and ADCpBridge.isWorking(vehicle)) or #ADHitch.rearImplementsOf(vehicle) == 0 + local action = ADFlowWagons.orphanAction({owned = owned, idleMs = idle + elapsed}) + if action == "none" then + orphans[vehicle] = nil + elseif action == "home" then + orphans[vehicle] = nil + Logging.info(ADFlowWagons.LOG_PREFIX .. "'%s' har et redskab på uden opgave (hentet før genindlæsning?) — sættes tilbage og kører hjem", + tostring(ADRuns.vehicleLabel(vehicle))) + goHome(adEnv, vehicle) + else + orphans[vehicle] = idle + elapsed + end + end +end + function ADFlowWagons.isEmptying(vehicle) return emptying[vehicle] ~= nil end @@ -601,7 +642,7 @@ local function cleanupAfterLoad(adEnv) and not ADFlowWagons.isPoolBusy(vehicle, vehicleId) then Logging.info(ADFlowWagons.LOG_PREFIX .. "flow '%s' er stoppet: '%s' tømmer og sætter sin vogn på plads", tostring(run.name), tostring(ADRuns.vehicleLabel(vehicle))) - pcall(ADFlowWagons.homeVehicle, adEnv, vehicle, run.name) + pcall(ADFlowWagons.homeVehicle, adEnv, vehicle, run.name, "afterLoad") end end end @@ -617,6 +658,8 @@ function ADFlowWagons.tick(adEnv, dt) emptyTimer = emptyTimer + dt if emptyTimer >= 2000 then emptyTimer = 0 + local okOrphan, errOrphan = pcall(tickOrphans, adEnv, 2000) + if not okOrphan then Logging.warning(ADFlowWagons.LOG_PREFIX .. "redskaber uden opgave: %s", tostring(errOrphan)) end local okEmpty, errEmpty = pcall(tickEmptying, adEnv) if not okEmpty then Logging.warning(ADFlowWagons.LOG_PREFIX .. "tømning: %s", tostring(errEmpty)) end end diff --git a/FS25_ADSmartPickup/modDesc.xml b/FS25_ADSmartPickup/modDesc.xml index 3acf30e..850e4ec 100644 --- a/FS25_ADSmartPickup/modDesc.xml +++ b/FS25_ADSmartPickup/modDesc.xml @@ -1,7 +1,7 @@ masterdraco - 1.60.3.0 + 1.60.4.0 <en>AD Smart Pickup</en> diff --git a/tests/test_adFlowWagons.lua b/tests/test_adFlowWagons.lua index 1bdbe59..fb80e3e 100644 --- a/tests/test_adFlowWagons.lua +++ b/tests/test_adFlowWagons.lua @@ -115,5 +115,13 @@ check("manuel kobling: kørende flow, egen vogn -> start", W.startAfterManualAtt check("manuel kobling: stoppet flow -> nej", W.startAfterManualAttach({flowRunning = false, ownWagon = true}), false) check("manuel kobling: AD kører allerede -> nej", W.startAfterManualAttach({flowRunning = true, ownWagon = true, adActive = true}), false) check("manuel kobling: fremmed vogn -> nej", W.startAfterManualAttach({flowRunning = true, ownWagon = false}), false) +-- husk vogn ved hjemtur: kun når flowet KØRTE med den (stop); ikke ved oprydning efter indlæsning, hvor traktoren +-- kan have et puljeredskab på fra et lån (in-game 29/9: Biogas Silage "huskede" en læssevogn fra markarbejdet) +check("husk ved stop af kørende flow", W.shouldRememberOnHome("stop"), true) +check("husk ikke ved oprydning efter indlæsning", W.shouldRememberOnHome("afterLoad"), false) +-- forældreløs påkobling (hentet før genindlæsning, opgaven tabt): sættes tilbage efter 2 min uden ejer +check("forældreløs: ingen ejer, længe nok -> hjem", W.orphanAction({owned = false, idleMs = W.ORPHAN_MS}), "home") +check("forældreløs: har ejer -> intet", W.orphanAction({owned = true, idleMs = W.ORPHAN_MS}), "none") +check("forældreløs: for kort tid -> vent", W.orphanAction({owned = false, idleMs = 1000}), "wait") print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) os.exit(failures == 0 and 0 or 1)