From 1759d6260095edc4fa2b42e5733aaa9ea30b42d5 Mon Sep 17 00:00:00 2001 From: masterdraco Date: Mon, 28 Sep 2026 20:06:03 +0200 Subject: [PATCH] =?UTF-8?q?fix(marksilo):=20fuld=20fabrik=20=E2=80=94=20l?= =?UTF-8?q?=C3=A5nt=20vogn=20med=20last=20der=20holder=20ved=20et=20lager?= =?UTF-8?q?=20uden=20plads=20i=2060=20s,=20k=C3=B8rer=20resten=20til=20et?= =?UTF-8?q?=20andet=20lager=20(g=C3=A5rdsilo)=20(v1.50.5.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FS25_ADSmartPickup/adFieldSiloPlanner.lua | 17 ++++++- FS25_ADSmartPickup/adFieldSilos.lua | 61 ++++++++++++++++------- FS25_ADSmartPickup/modDesc.xml | 2 +- tests/test_adFieldSiloPlanner.lua | 11 ++++ 4 files changed, 70 insertions(+), 21 deletions(-) diff --git a/FS25_ADSmartPickup/adFieldSiloPlanner.lua b/FS25_ADSmartPickup/adFieldSiloPlanner.lua index f853c93..a7f69e0 100644 --- a/FS25_ADSmartPickup/adFieldSiloPlanner.lua +++ b/FS25_ADSmartPickup/adFieldSiloPlanner.lua @@ -54,9 +54,22 @@ function ADFieldSiloPlanner.restDue(s) and (s.cargo or 0) >= ADFieldSiloPlanner.REST_MIN_LITERS and (s.siloStock or 0) < ADFieldSiloPlanner.REST_MIN_LITERS end +-- Fuld fabrik/lager: vognen med last har holdt ved sit lager i STORE_FULL_MS, og lageret har ikke plads. +-- s = {atStore, stillMs, cargo, storeFree} +ADFieldSiloPlanner.STORE_FULL_MS = 60000 +function ADFieldSiloPlanner.storeFullDue(s) + return s.atStore == true and (s.stillMs or 0) >= ADFieldSiloPlanner.STORE_FULL_MS + and (s.cargo or 0) >= ADFieldSiloPlanner.REST_MIN_LITERS and (s.storeFree or 0) < ADFieldSiloPlanner.REST_MIN_LITERS +end + -- Lager til en rest: fabrik kun med plads til hele resten, ellers gårdlager (nærmeste med plads, ellers mest plads). -function ADFieldSiloPlanner.restStore(stores, silo, fillType, liters) - return chooseStore(stores, silo, fillType, liters, 1, {}, true) or chooseStore(stores, silo, fillType, liters, 1, {}, false) +-- excludeId: lageret vognen holder fast ved (fuldt). +function ADFieldSiloPlanner.restStore(stores, silo, fillType, liters, excludeId) + local candidates = {} + for _, store in ipairs(stores or {}) do + if store.id ~= excludeId then table.insert(candidates, store) end + end + return chooseStore(candidates, silo, fillType, liters, 1, {}, true) or chooseStore(candidates, silo, fillType, liters, 1, {}, false) end local function canCarry(vehicle, fillType) diff --git a/FS25_ADSmartPickup/adFieldSilos.lua b/FS25_ADSmartPickup/adFieldSilos.lua index 96d5752..5da5457 100644 --- a/FS25_ADSmartPickup/adFieldSilos.lua +++ b/FS25_ADSmartPickup/adFieldSilos.lua @@ -455,7 +455,12 @@ function ADFieldSilos.adoptOrphans(adEnv, silos) local silo = first ~= nil and byMarker[first.id] or nil if silo ~= nil then local fillType = module.getFillType ~= nil and module:getFillType() or nil - loans[vehicle] = {siloId = silo.id, siloName = silo.name, fillType = fillType, liters = 0, startedMs = nowMs, + local second = module.getSecondMarker ~= nil and module:getSecondMarker() or nil + local storeId = nil + for _, store in ipairs(ADFieldSilos.lastStores or {}) do + if second ~= nil and store.markerId == second.id then storeId = store.id end + end + loans[vehicle] = {siloId = silo.id, storeId = storeId, siloName = silo.name, fillType = fillType, liters = 0, startedMs = nowMs, lastProgressMs = nowMs, lastFill = fillLevel(adEnv, vehicle), hasProgressed = true, adopted = true} Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s' overtaget igen (AutoDrive kører fra %s efter genindlæsning)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(silo.name)) @@ -467,22 +472,41 @@ end -- Tom silo-vagt: en lånt vogn med last, der står stille ved en tom marksilo, kører resten videre — til en fabrik -- med plads til hele resten, ellers til et gårdlager (AutoDrive venter ellers til vognen er fuld). local warnedNoRestStore = {} -local function checkRest(adEnv, vehicle, loan, moving, fill) - if loan.delivering or loan.fetching then return end - local silo = nil - for _, candidate in ipairs(ADFieldSilos.lastSilos or {}) do - if candidate.id == loan.siloId then silo = candidate end - end - local wayPoint = silo ~= nil and silo.markerId ~= nil and adEnv.ADGraphManager:getWayPointById(silo.markerId) or nil - if wayPoint == nil or vehicle.rootNode == nil then return end +local function isNear(adEnv, vehicle, markerId) + local wayPoint = markerId ~= nil and adEnv.ADGraphManager:getWayPointById(markerId) or nil + if wayPoint == nil or vehicle.rootNode == nil then return false end local x, _, z = getWorldTranslation(vehicle.rootNode) - local atSilo = (x - wayPoint.x) ^ 2 + (z - wayPoint.z) ^ 2 <= ADFieldSilos.REST_SILO_DISTANCE ^ 2 - if moving or not atSilo then loan.stillSince = nil return end + return (x - wayPoint.x) ^ 2 + (z - wayPoint.z) ^ 2 <= ADFieldSilos.REST_SILO_DISTANCE ^ 2 +end + +local function findById(list, id) + for _, item in ipairs(list or {}) do + if item.id == id then return item end + end + return nil +end + +local function checkRest(adEnv, vehicle, loan, moving, fill) + if loan.fetching then return end + local silo = findById(ADFieldSilos.lastSilos, loan.siloId) + if silo == nil then return end + if moving then loan.stillSince = nil return end loan.stillSince = loan.stillSince or nowMs - local state = {atSilo = atSilo, stillMs = nowMs - loan.stillSince, - siloStock = (silo.stock or {})[loan.fillType] or 0, cargo = fill} - if not ADFieldSiloPlanner.restDue(state) then return end - local store = ADFieldSiloPlanner.restStore(ADFieldSilos.lastStores, silo, loan.fillType, fill) + local stillMs = nowMs - loan.stillSince + local fullStore = nil + if not loan.delivering and isNear(adEnv, vehicle, silo.markerId) then + -- tom marksilo med last på + local state = {atSilo = true, stillMs = stillMs, siloStock = (silo.stock or {})[loan.fillType] or 0, cargo = fill} + if not ADFieldSiloPlanner.restDue(state) then return end + else + -- fuldt lager (fabrik der kun tager sit forbrug) med last på + local current = findById(ADFieldSilos.lastStores, loan.storeId) + if current == nil or not isNear(adEnv, vehicle, current.markerId) then return end + local state = {atStore = true, stillMs = stillMs, cargo = fill, storeFree = (current.free or {})[loan.fillType] or 0} + if not ADFieldSiloPlanner.storeFullDue(state) then return end + fullStore = current + end + local store = ADFieldSiloPlanner.restStore(ADFieldSilos.lastStores, silo, loan.fillType, fill, fullStore ~= nil and fullStore.id or nil) if store == nil then if not warnedNoRestStore[vehicle] then warnedNoRestStore[vehicle] = true @@ -492,13 +516,14 @@ local function checkRest(adEnv, vehicle, loan, moving, fill) return end warnedNoRestStore[vehicle] = nil - loan.delivering = true + loan.delivering, loan.storeId, loan.stillSince = true, store.id, nil loan.startedMs, loan.hasProgressed = nowMs, true local isPool = ADHitch ~= nil and #ADHitch.poolParkIds(adEnv, vehicle) > 0 if not isPool then ADFieldWork.enableParkAtJobFinished(vehicle) end ADFieldWork.startAd(adEnv, vehicle, adEnv.AutoDrive.MODE_DELIVERTO, store.markerId, nil, loan.fillType) - Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s': %s er tom — kører resten (%d l %s) til %s", - tostring(ADRuns.vehicleLabel(vehicle)), tostring(silo.name), math.floor(fill), fillTypeName(loan.fillType), tostring(store.name)) + Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s': %s — kører resten (%d l %s) til %s", + tostring(ADRuns.vehicleLabel(vehicle)), fullStore ~= nil and (tostring(fullStore.name) .. " er fuld") or (tostring(silo.name) .. " er tom"), + math.floor(fill), fillTypeName(loan.fillType), tostring(store.name)) end local function checkLoans(adEnv) diff --git a/FS25_ADSmartPickup/modDesc.xml b/FS25_ADSmartPickup/modDesc.xml index a21cb2d..a5d5e2a 100644 --- a/FS25_ADSmartPickup/modDesc.xml +++ b/FS25_ADSmartPickup/modDesc.xml @@ -1,7 +1,7 @@ masterdraco - 1.50.4.0 + 1.50.5.0 <en>AD Smart Pickup</en> diff --git a/tests/test_adFieldSiloPlanner.lua b/tests/test_adFieldSiloPlanner.lua index bfa6554..91ae24b 100644 --- a/tests/test_adFieldSiloPlanner.lua +++ b/tests/test_adFieldSiloPlanner.lua @@ -144,5 +144,16 @@ local restStores = { check("RS6 fabrik uden plads til hele resten -> gårdsilo", P.restStore(restStores, {x = 0, z = 0}, 10, 12000).id, "gaard") check("RS7 fabrik med plads -> fabrik", P.restStore(restStores, {x = 0, z = 0}, 10, 4000).id, "fab") check("RS8 intet tager varen", P.restStore(restStores, {x = 0, z = 0}, 99, 4000), nil) +-- Fuld fabrik: lånt vogn med last holder ved et lager uden plads -> resten til et andet lager (gård) +check("SF1 fuld fabrik -> videre", P.storeFullDue({atStore = true, stillMs = 70000, cargo = 12000, storeFree = 0}), true) +check("SF2 fabrikken tager stadig imod -> vent", P.storeFullDue({atStore = true, stillMs = 70000, cargo = 12000, storeFree = 8000}), false) +check("SF3 lige ankommet -> vent", P.storeFullDue({atStore = true, stillMs = 20000, cargo = 12000, storeFree = 0}), false) +check("SF4 ikke ved lageret -> nej", P.storeFullDue({atStore = false, stillMs = 70000, cargo = 12000, storeFree = 0}), false) +local fullStores = { + {id = "fab", kind = "production", markerId = 1, x = 10, z = 0, free = {[10] = 0}}, + {id = "gaard", kind = "silo", markerId = 2, x = 500, z = 0, free = {[10] = 900000}}, +} +check("SF5 andet lager end det fulde", P.restStore(fullStores, {x = 0, z = 0}, 10, 12000, "fab").id, "gaard") +check("SF6 kun det fulde tager varen -> intet", P.restStore({fullStores[1]}, {x = 0, z = 0}, 10, 12000, "fab"), nil) print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) os.exit(failures == 0 and 0 or 1)