feat(pulje): etape 3 — marksilo-flowet låner også ledig solo-traktor + puljevogn: henter vognen, kører Hent og aflever, sætter vognen af og kører hjem; høstreserven tæller puljevogne (v1.50.0.0)
This commit is contained in:
@@ -267,6 +267,24 @@ function ADFieldSilos.collectVehicles(adEnv)
|
||||
byId[rig.id] = rig.vehicle
|
||||
end
|
||||
end
|
||||
-- puljevogne: en ledig solo-traktor henter vognen først (maskinpulje etape 3)
|
||||
local poolById = {}
|
||||
if ADPool ~= nil then
|
||||
local okPool, implements, tractors = pcall(ADPool.collect, adEnv, function(v)
|
||||
return ADFieldWork.isBusyVehicle(v, ADRunsController.getVehicleId(v))
|
||||
end)
|
||||
if okPool then
|
||||
for _, pair in ipairs(ADPool.pairAll("unloader", implements, tractors, ADPool.blocked(ADFieldJobs.now or 0))) do
|
||||
local entryId = "pool:" .. tostring(pair.implement.id)
|
||||
table.insert(vehicles, {id = entryId, x = pair.implement.x, z = pair.implement.z,
|
||||
capacity = pair.implement.capacity or 0, carries = pair.implement.carries or {}})
|
||||
byId[entryId] = pair.tractor.vehicle
|
||||
poolById[entryId] = pair
|
||||
end
|
||||
else
|
||||
Logging.warning(ADFieldSilos.LOG_PREFIX .. "maskinpuljen kunne ikke læses: %s", tostring(implements))
|
||||
end
|
||||
end
|
||||
local ok, needs = pcall(ADFieldSilos.harvestNeeds, adEnv, rigs)
|
||||
if ok and #needs > 0 then
|
||||
local before = #vehicles
|
||||
@@ -277,7 +295,7 @@ function ADFieldSilos.collectVehicles(adEnv)
|
||||
end
|
||||
why.eligible = #vehicles
|
||||
ADFieldSilos.lastVehicleReasons = why
|
||||
return vehicles, byId
|
||||
return vehicles, byId, poolById
|
||||
end
|
||||
|
||||
-- Høsten først: pr. høster der arbejder (CP kører) holdes dens planlagte antal tømmevogne tilbage, minus dem
|
||||
@@ -346,6 +364,33 @@ local function dispatchOne(adEnv, order, vehicle, silosById, storesById)
|
||||
tostring(store ~= nil and store.name or order.storeId))
|
||||
end
|
||||
|
||||
-- Puljevogn: traktoren henter vognen ved "Connect X" og kører derefter turen som en almindelig tømmevogn.
|
||||
local function dispatchPool(adEnv, order, pair, silosById, storesById)
|
||||
local tractor = pair.tractor.vehicle
|
||||
local silo = silosById[order.siloId]
|
||||
local owner = {siloId = order.siloId, storeId = order.storeId, siloName = silo ~= nil and silo.name or order.siloId,
|
||||
fillType = order.fillType, liters = order.liters, startedMs = nowMs, lastProgressMs = nowMs, lastFill = 0, fetching = true}
|
||||
loans[tractor] = owner
|
||||
ADPool.reserve(owner, {pair.implement.id, pair.tractor.id})
|
||||
ADHitch.fetch(adEnv, tractor, pair.implement.connectId, function(_, ok, detail)
|
||||
ADPool.release(owner)
|
||||
if loans[tractor] ~= owner then return end -- lånet blev afbrudt imens (Stop alt / flow slået fra)
|
||||
if not ok then
|
||||
loans[tractor] = nil
|
||||
local blamed = ADPool.failureBlames(detail) == "tractor" and pair.tractor.id or pair.implement.id
|
||||
ADPool.quarantine(blamed, ADFieldJobs.now or 0)
|
||||
Logging.warning(ADFieldSilos.LOG_PREFIX .. "'%s' kunne ikke hente puljevognen '%s' (%s) — prøver en anden om lidt",
|
||||
tostring(ADRuns.vehicleLabel(tractor)), tostring(pair.implement.name), tostring(detail))
|
||||
local park = ADFieldWork.parkMarkerId(adEnv, tractor)
|
||||
if park ~= nil then ADFieldWork.startAd(adEnv, tractor, adEnv.AutoDrive.MODE_DRIVETO, park, nil) end
|
||||
return
|
||||
end
|
||||
dispatchOne(adEnv, order, tractor, silosById, storesById)
|
||||
end)
|
||||
Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s' henter puljevognen '%s' til %d l %s i %s", tostring(ADRuns.vehicleLabel(tractor)),
|
||||
tostring(pair.implement.name), math.floor(order.liters), fillTypeName(order.fillType), tostring(silo ~= nil and silo.name or order.siloId))
|
||||
end
|
||||
|
||||
local function release(adEnv, vehicle, reason)
|
||||
local loan = loans[vehicle]
|
||||
loans[vehicle] = nil
|
||||
@@ -361,6 +406,14 @@ local function release(adEnv, vehicle, reason)
|
||||
pcall(vehicle.stopAutoDrive, vehicle)
|
||||
end
|
||||
Logging.info(ADFieldSilos.LOG_PREFIX .. "'%s' frigivet (%s)", tostring(ADRuns.vehicleLabel(vehicle)), tostring(reason))
|
||||
-- puljevogn bag traktoren: sæt den af på sin plads og kør hjem (ikke når spilleren har overtaget)
|
||||
if reason ~= "player" and ADHitch ~= nil then
|
||||
local okHome, pooled = pcall(ADHitch.returnHome, adEnv, vehicle)
|
||||
if not (okHome and pooled) and loan.fetching then
|
||||
local park = ADFieldWork.parkMarkerId(adEnv, vehicle)
|
||||
if park ~= nil then ADFieldWork.startAd(adEnv, vehicle, adEnv.AutoDrive.MODE_DRIVETO, park, nil) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ADFieldSilos.stopAll(adEnv)
|
||||
@@ -378,6 +431,8 @@ local function checkLoans(adEnv)
|
||||
else
|
||||
local ok, err = pcall(function()
|
||||
local loan = loans[vehicle]
|
||||
-- henter puljevognen: AD holder stille under koblingen — ikke "færdig"
|
||||
if loan.fetching then return end
|
||||
local stateModule = vehicle.ad ~= nil and vehicle.ad.stateModule or nil
|
||||
local fill = fillLevel(adEnv, vehicle)
|
||||
local vehicleState = {
|
||||
@@ -429,7 +484,7 @@ end
|
||||
function ADFieldSilos.planNow(adEnv)
|
||||
local cfg = ADFieldSilos.config
|
||||
local silos, stores, byId = ADFieldSilos.collectBuildings(adEnv)
|
||||
local vehicles, vehiclesById = ADFieldSilos.collectVehicles(adEnv)
|
||||
local vehicles, vehiclesById, poolById = ADFieldSilos.collectVehicles(adEnv)
|
||||
local feedReserve, farmStock = nil, nil
|
||||
if cfg.toProduction then
|
||||
local ok, reserve, stock = pcall(ADFieldSilos.collectFeed, stores, byId, farmId(), cfg.reserveDays)
|
||||
@@ -451,7 +506,14 @@ function ADFieldSilos.planNow(adEnv)
|
||||
if vehicle ~= nil and not hasRoutes(adEnv, vehicle, order) then
|
||||
vehicle = nil
|
||||
end
|
||||
if vehicle ~= nil then
|
||||
local pair = poolById ~= nil and poolById[order.vehicleId] or nil
|
||||
if vehicle ~= nil and pair ~= nil then
|
||||
local ok, err = pcall(dispatchPool, adEnv, order, pair, silosById, storesById)
|
||||
if not ok then
|
||||
loans[vehicle] = nil
|
||||
Logging.warning(ADFieldSilos.LOG_PREFIX .. "kunne ikke sende '%s' efter puljevogn: %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(err))
|
||||
end
|
||||
elseif vehicle ~= nil then
|
||||
local ok, err = pcall(dispatchOne, adEnv, order, vehicle, silosById, storesById)
|
||||
if not ok then
|
||||
loans[vehicle] = nil
|
||||
|
||||
@@ -153,6 +153,25 @@ function ADPool.pairFor(role, fieldX, fieldZ, implements, tractors, blocked, acc
|
||||
return nil, "tooWeak", {weakest ~= nil and weakest.neededHp or 0, weakest ~= nil and weakest.name or "?"}
|
||||
end
|
||||
|
||||
-- Alle frie puljeredskaber med rollen, hver parret med den nærmeste endnu ubrugte traktor med nok hk
|
||||
-- (marksilo-flowet planlægger over mange vogne på én gang).
|
||||
function ADPool.pairAll(role, implements, tractors, blocked)
|
||||
blocked = blocked or {}
|
||||
local used, result = {}, {}
|
||||
for _, implement in ipairs(implements or {}) do
|
||||
if hasRole(implement, role) and not blocked[implement.id] then
|
||||
local tractor = nearest(tractors or {}, implement.x, implement.z, function(t)
|
||||
return not used[t.id] and not blocked[t.id] and not t.offNetwork and ADPool.powerOk(t.hp, implement.neededHp)
|
||||
end)
|
||||
if tractor ~= nil then
|
||||
used[tractor.id] = true
|
||||
table.insert(result, {implement = implement, tractor = tractor})
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
-- Ventende marker prøver igen på fælles taktslag (ikke hver sin 30 s fra eget forsøg): så udløber de i samme
|
||||
-- tick, og køens rækkefølge (længst ventende først) afgør hvem der får den næste ledige traktor.
|
||||
function ADPool.alignedRetry(nowMs, periodMs)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<modDesc descVersion="107">
|
||||
<author>masterdraco</author>
|
||||
<version>1.49.0.0</version>
|
||||
<version>1.50.0.0</version>
|
||||
<title>
|
||||
<en>AD Smart Pickup</en>
|
||||
</title>
|
||||
|
||||
@@ -141,5 +141,13 @@ check("bære: vare understøttet", P.canCarry({carries = {[3] = true}}, 3), true
|
||||
check("bære: vare ikke understøttet", P.canCarry({carries = {[3] = true}}, 7), false)
|
||||
check("bære: ingen vare krævet", P.canCarry({carries = {}}, nil), true)
|
||||
check("bære: ukendt last", P.canCarry({}, 3), false)
|
||||
-- etape 3: alle puljevogne parret med hver sin nærmeste traktor (en traktor bruges kun én gang)
|
||||
local wagons = {{id = "v1", role = "unloader", x = 0, z = 0}, {id = "v2", role = "unloader", x = 100, z = 0},
|
||||
{id = "v3", role = "unloader", x = 200, z = 0}, {id = "plovX", role = "plow", x = 0, z = 0}}
|
||||
local pairs3 = P.pairAll("unloader", wagons, {{id = "tA", x = 10, z = 0}, {id = "tB", x = 90, z = 0}}, {v2 = true})
|
||||
check("par-alle: antal (v2 reserveret, 2 traktorer)", #pairs3, 2)
|
||||
check("par-alle: v1 -> tA", pairs3[1].implement.id .. ">" .. pairs3[1].tractor.id, "v1>tA")
|
||||
check("par-alle: v3 -> tB (tA er brugt)", pairs3[2].implement.id .. ">" .. pairs3[2].tractor.id, "v3>tB")
|
||||
check("par-alle: ingen traktorer", #P.pairAll("unloader", wagons, {}, {}), 0)
|
||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||
os.exit(failures == 0 and 0 or 1)
|
||||
|
||||
Reference in New Issue
Block a user