feat(ui): Flows-oprydning — tavle grupperet Ind/Ud efter navn, traktorer: egne+ledige (Vis alle), bygninger: valgte først, uden markør skjult (Vis alle); fix: staldes foderkrybbe (feedingTrough) i stationsopslag og bygningsmarkører — hønsehus (v1.19.0.0)
This commit is contained in:
@@ -104,6 +104,11 @@ local function collectNodes(placeable, loadStations, unloadStations)
|
|||||||
end
|
end
|
||||||
if #nodes > 0 then table.insert(loadGroups, nodes) end
|
if #nodes > 0 then table.insert(loadGroups, nodes) end
|
||||||
end
|
end
|
||||||
|
-- staldens foderkrybbe (hønsehus: kun krybben, ingen trigger i aflæsningsstationen)
|
||||||
|
local food = placeable.spec_husbandryFood
|
||||||
|
local trough = food ~= nil and food.feedingTrough or nil
|
||||||
|
local troughNode = trough ~= nil and (trough.exactFillRootNode or trough.triggerNode) or nil
|
||||||
|
if troughNode ~= nil then table.insert(unloadNodes, troughNode) end
|
||||||
-- stald med egne pallespawnere (hønsehus: æg, fårestald: uld) — én læssegruppe pr. spawner
|
-- stald med egne pallespawnere (hønsehus: æg, fårestald: uld) — én læssegruppe pr. spawner
|
||||||
local husbandryPallets = placeable.spec_husbandryPallets
|
local husbandryPallets = placeable.spec_husbandryPallets
|
||||||
local seenSpawners = {}
|
local seenSpawners = {}
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
-- AD Flow View
|
||||||
|
-- Rene regler for Flows-fanens oprydning (ingen spil-API): tavlens grupper og rækkefølge, hvilke
|
||||||
|
-- traktorer og bygninger der vises som standard, og hvad "Vis alle" tilføjer.
|
||||||
|
|
||||||
|
ADFlowView = {}
|
||||||
|
|
||||||
|
-- Naturlig sortering: tal i navne sammenlignes som tal ("Biogas 9" < "Biogas 10").
|
||||||
|
local function naturalKey(text)
|
||||||
|
local parts = {}
|
||||||
|
local value = string.lower(tostring(text or ""))
|
||||||
|
local position = 1
|
||||||
|
while position <= #value do
|
||||||
|
local digits = string.match(value, "^%d+", position)
|
||||||
|
if digits ~= nil then
|
||||||
|
table.insert(parts, {number = tonumber(digits)})
|
||||||
|
position = position + #digits
|
||||||
|
else
|
||||||
|
local chunk = string.match(value, "^%D+", position)
|
||||||
|
table.insert(parts, {text = chunk})
|
||||||
|
position = position + #chunk
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return parts
|
||||||
|
end
|
||||||
|
|
||||||
|
function ADFlowView.naturalLess(a, b)
|
||||||
|
local ka, kb = naturalKey(a), naturalKey(b)
|
||||||
|
for index = 1, math.max(#ka, #kb) do
|
||||||
|
local pa, pb = ka[index], kb[index]
|
||||||
|
if pa == nil then return true end
|
||||||
|
if pb == nil then return false end
|
||||||
|
if pa.number ~= nil and pb.number ~= nil then
|
||||||
|
if pa.number ~= pb.number then return pa.number < pb.number end
|
||||||
|
elseif pa.number ~= nil or pb.number ~= nil then
|
||||||
|
return pa.number ~= nil
|
||||||
|
elseif pa.text ~= pb.text then
|
||||||
|
return pa.text < pb.text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sortedBy(list, field)
|
||||||
|
local copy = {}
|
||||||
|
for _, item in ipairs(list or {}) do table.insert(copy, item) end
|
||||||
|
table.sort(copy, function(a, b)
|
||||||
|
if a[field] ~= b[field] then return ADFlowView.naturalLess(a[field], b[field]) end
|
||||||
|
return tostring(a.id) < tostring(b.id)
|
||||||
|
end)
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Tavlen: forsyning ("Ind til bygning") først, så udkørsel ("Ud fra bygning"); hver gruppe efter navn.
|
||||||
|
-- {{kind, runs}, ...}; tomme grupper udelades.
|
||||||
|
function ADFlowView.boardGroups(runs)
|
||||||
|
local byKind = {supply = {}, outbound = {}}
|
||||||
|
for _, run in ipairs(runs or {}) do
|
||||||
|
table.insert(byKind[run.kind == "outbound" and "outbound" or "supply"], run)
|
||||||
|
end
|
||||||
|
local groups = {}
|
||||||
|
for _, kind in ipairs({"supply", "outbound"}) do
|
||||||
|
if #byKind[kind] > 0 then
|
||||||
|
table.insert(groups, {kind = kind, runs = sortedBy(byKind[kind], "name")})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return groups
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Samme rækkefølge som tavlen, som én liste (flow-vælgeren).
|
||||||
|
function ADFlowView.orderedRuns(runs)
|
||||||
|
local result = {}
|
||||||
|
for _, group in ipairs(ADFlowView.boardGroups(runs)) do
|
||||||
|
for _, run in ipairs(group.runs) do table.insert(result, run) end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Traktorer: vehicles = {{id, label, state = "in"|"free"|"other"|"blocked"}}. Standard: flowets egne,
|
||||||
|
-- så ledige der kan bruges. showAll tilføjer traktorer i andre flows og låste (vogn passer ikke).
|
||||||
|
local STATE_ORDER = {"in", "free", "other", "blocked"}
|
||||||
|
|
||||||
|
function ADFlowView.vehicleRows(vehicles, showAll)
|
||||||
|
local byState = {}
|
||||||
|
for _, entry in ipairs(vehicles or {}) do
|
||||||
|
byState[entry.state] = byState[entry.state] or {}
|
||||||
|
table.insert(byState[entry.state], entry)
|
||||||
|
end
|
||||||
|
local rows = {}
|
||||||
|
for _, state in ipairs(STATE_ORDER) do
|
||||||
|
if showAll or state == "in" or state == "free" then
|
||||||
|
for _, entry in ipairs(sortedBy(byState[state], "label")) do table.insert(rows, entry) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return rows
|
||||||
|
end
|
||||||
|
|
||||||
|
function ADFlowView.hiddenCount(all, shown)
|
||||||
|
return #(all or {}) - #(shown or {})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Bygninger: buildings = {{id, name, hasMarker}}, chosen = {[id] = true}. Valgte først; bygninger uden
|
||||||
|
-- markør kun hvis valgte eller showAll (de kan alligevel ikke bruges før en markør er sat).
|
||||||
|
function ADFlowView.buildingRows(buildings, chosen, showAll)
|
||||||
|
local picked, withMarker, withoutMarker = {}, {}, {}
|
||||||
|
for _, building in ipairs(buildings or {}) do
|
||||||
|
if chosen ~= nil and chosen[building.id] then
|
||||||
|
table.insert(picked, building)
|
||||||
|
elseif building.hasMarker then
|
||||||
|
table.insert(withMarker, building)
|
||||||
|
elseif showAll then
|
||||||
|
table.insert(withoutMarker, building)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local rows = {}
|
||||||
|
for _, list in ipairs({sortedBy(picked, "name"), sortedBy(withMarker, "name"), sortedBy(withoutMarker, "name")}) do
|
||||||
|
for _, building in ipairs(list) do table.insert(rows, building) end
|
||||||
|
end
|
||||||
|
return rows
|
||||||
|
end
|
||||||
@@ -167,8 +167,48 @@ local function getLoadStationAtMarker(adEnv, wayPoint, farmId)
|
|||||||
return getClosestStation(adEnv, g_currentMission.storageSystem:getLoadingStations(), "loadTriggers", LOAD_TRIGGER_NODE_FIELDS, wayPoint, farmId)
|
return getClosestStation(adEnv, g_currentMission.storageSystem:getLoadingStations(), "loadTriggers", LOAD_TRIGGER_NODE_FIELDS, wayPoint, farmId)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Staldes foderkrybbe (spec_husbandryFood.feedingTrough, samme tippe-trigger som AutoDrive bruger) står
|
||||||
|
-- ikke altid i aflæsningsstationens unloadTriggers — hønsehuset har KUN krybben. Opslaget får derfor en
|
||||||
|
-- proxy pr. krybbe der peger på staldens station (eller en minimal station). Caches i UNLOAD_CACHE_MS.
|
||||||
|
ADSmartPickup.UNLOAD_CACHE_MS = 1000
|
||||||
|
local unloadCache = {list = nil, time = -math.huge}
|
||||||
|
|
||||||
|
function ADSmartPickup.invalidateUnloadCandidates()
|
||||||
|
unloadCache.list, unloadCache.time = nil, -math.huge
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getUnloadCandidates()
|
||||||
|
local now = g_currentMission ~= nil and type(g_currentMission.time) == "number" and g_currentMission.time or nil
|
||||||
|
if unloadCache.list ~= nil and now ~= nil and (now - unloadCache.time) < ADSmartPickup.UNLOAD_CACHE_MS then
|
||||||
|
return unloadCache.list
|
||||||
|
end
|
||||||
|
local list, byPlaceable = {}, {}
|
||||||
|
for _, station in pairs(g_currentMission.storageSystem:getUnloadingStations()) do
|
||||||
|
table.insert(list, station)
|
||||||
|
if station.owningPlaceable ~= nil and byPlaceable[station.owningPlaceable] == nil then
|
||||||
|
byPlaceable[station.owningPlaceable] = station
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local placeables = g_currentMission.placeableSystem ~= nil and g_currentMission.placeableSystem.placeables or {}
|
||||||
|
for _, placeable in pairs(placeables) do
|
||||||
|
local food = placeable.spec_husbandryFood
|
||||||
|
local trough = food ~= nil and food.feedingTrough or nil
|
||||||
|
local node = trough ~= nil and (trough.exactFillRootNode or trough.triggerNode) or nil
|
||||||
|
if node ~= nil then
|
||||||
|
local station = byPlaceable[placeable] or {
|
||||||
|
owningPlaceable = placeable,
|
||||||
|
-- spillets adgangstjek kalder getOwnerFarmId på stationen
|
||||||
|
getOwnerFarmId = function() return placeable.getOwnerFarmId ~= nil and placeable:getOwnerFarmId() or placeable.ownerFarmId end,
|
||||||
|
}
|
||||||
|
table.insert(list, setmetatable({unloadTriggers = {{exactFillRootNode = node}}}, {__index = station}))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unloadCache.list, unloadCache.time = list, now or -math.huge
|
||||||
|
return list
|
||||||
|
end
|
||||||
|
|
||||||
local function getUnloadStationAtMarker(adEnv, wayPoint, farmId)
|
local function getUnloadStationAtMarker(adEnv, wayPoint, farmId)
|
||||||
return getClosestStation(adEnv, g_currentMission.storageSystem:getUnloadingStations(), "unloadTriggers", UNLOAD_TRIGGER_NODE_FIELDS, wayPoint, farmId)
|
return getClosestStation(adEnv, getUnloadCandidates(), "unloadTriggers", UNLOAD_TRIGGER_NODE_FIELDS, wayPoint, farmId)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Station ved et AutoDrive-waypoint (bruges af runs-controlleren og læs-byttet); nil uden station.
|
-- Station ved et AutoDrive-waypoint (bruges af runs-controlleren og læs-byttet); nil uden station.
|
||||||
|
|||||||
@@ -70,11 +70,15 @@ function SmartPickupFrame:fillBoardRows(adEnv)
|
|||||||
local rows = {}
|
local rows = {}
|
||||||
local header = self:addTextRow(self.i18n:getText("spu_section_flows"))
|
local header = self:addTextRow(self.i18n:getText("spu_section_flows"))
|
||||||
table.insert(rows, header.parent)
|
table.insert(rows, header.parent)
|
||||||
for _, run in ipairs(ADRunsController.store.runs) do
|
-- grupperet: Ind til bygning, så Ud fra bygning — hver efter navn
|
||||||
|
for _, group in ipairs(ADFlowView.boardGroups(ADRunsController.store.runs)) do
|
||||||
|
table.insert(rows, self:addTextRow(self.i18n:getText(group.kind == "outbound" and "spu_board_outbound" or "spu_board_supply")).parent)
|
||||||
|
for _, run in ipairs(group.runs) do
|
||||||
local title = self:addTextRow(self:describeFlow(adEnv, run, run.id == self.selectedRunId))
|
local title = self:addTextRow(self:describeFlow(adEnv, run, run.id == self.selectedRunId))
|
||||||
table.insert(rows, title.parent)
|
table.insert(rows, title.parent)
|
||||||
table.insert(self.boardRows, {run = run, title = title})
|
table.insert(self.boardRows, {run = run, title = title})
|
||||||
end
|
end
|
||||||
|
end
|
||||||
if #ADRunsController.store.runs == 0 then
|
if #ADRunsController.store.runs == 0 then
|
||||||
table.insert(rows, self:addTextRow(self.i18n:getText("spu_noRuns")).parent)
|
table.insert(rows, self:addTextRow(self.i18n:getText("spu_noRuns")).parent)
|
||||||
end
|
end
|
||||||
@@ -126,17 +130,29 @@ function SmartPickupFrame:fillBuildingRows(adEnv, run, role)
|
|||||||
local rowKind = role == "load" and "sourceBuilding" or role == "store" and "storeBuilding" or "targetBuilding"
|
local rowKind = role == "load" and "sourceBuilding" or role == "store" and "storeBuilding" or "targetBuilding"
|
||||||
for _, id in ipairs(ids or {}) do chosen[id] = true end
|
for _, id in ipairs(ids or {}) do chosen[id] = true end
|
||||||
local count = 0
|
local count = 0
|
||||||
|
-- kandidater -> valgte først, så med markør; uden markør kun med "Vis alle bygninger"
|
||||||
|
local candidates = {}
|
||||||
for _, building in ipairs(ADBuildings.list(adEnv, g_currentMission:getFarmId())) do
|
for _, building in ipairs(ADBuildings.list(adEnv, g_currentMission:getFarmId())) do
|
||||||
-- "Lager til": siloer og gårdens fabrikker (fx BGA) — markøren er bygningens aflæsningsmarkør
|
-- "Lager til": siloer og gårdens fabrikker (fx BGA) — markøren er bygningens aflæsningsmarkør
|
||||||
local fits = (role == "load" and building.canBeSource) or (role == "unload" and building.canBeTarget)
|
local fits = (role == "load" and building.canBeSource) or (role == "unload" and building.canBeTarget)
|
||||||
or (role == "store" and (building.kind == "silo" or building.kind == "factory"))
|
or (role == "store" and (building.kind == "silo" or building.kind == "factory"))
|
||||||
if fits then
|
if fits then
|
||||||
|
local markers = ADBuildings.getMarkers ~= nil and ADBuildings.getMarkers(building, role == "store" and "unload" or role) or {}
|
||||||
|
table.insert(candidates, {id = building.id, name = building.name, hasMarker = markers[1] ~= nil, building = building})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local shown = ADFlowView.buildingRows(candidates, chosen, self.showAllBuildings == true)
|
||||||
|
local hiddenBuildings = ADFlowView.hiddenCount(candidates, shown)
|
||||||
|
if hiddenBuildings > 0 or self.showAllBuildings then
|
||||||
|
self:addToggleRow("showAllBuildings", string.format(self.i18n:getText("spu_showAllBuildings"), hiddenBuildings), {self.i18n:getText("ui_no"), self.i18n:getText("ui_yes")}, self.showAllBuildings == true)
|
||||||
|
end
|
||||||
|
for _, entry in ipairs(shown) do
|
||||||
|
local building = entry.building
|
||||||
count = count + 1
|
count = count + 1
|
||||||
local row = self:addRow(self.ingredientPrefab, {kind = rowKind, buildingId = building.id})
|
local row = self:addRow(self.ingredientPrefab, {kind = rowKind, buildingId = building.id})
|
||||||
row:getDescendantByName("title"):setText(self:describeBuilding(building, role == "store" and "unload" or role))
|
row:getDescendantByName("title"):setText(self:describeBuilding(building, role == "store" and "unload" or role))
|
||||||
row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
-- valgte bygninger der ikke længere findes (solgt)
|
-- valgte bygninger der ikke længere findes (solgt)
|
||||||
for _, id in ipairs(ids or {}) do
|
for _, id in ipairs(ids or {}) do
|
||||||
if ADBuildings.find(adEnv, g_currentMission:getFarmId(), id) == nil then
|
if ADBuildings.find(adEnv, g_currentMission:getFarmId(), id) == nil then
|
||||||
|
|||||||
@@ -267,7 +267,11 @@ function SmartPickupFrame:setStaticRowsVisible(tab, run)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Samme rækkefølge som tavlen: Ind til bygning først, så Ud fra bygning, hver efter navn.
|
||||||
function SmartPickupFrame:getRunsForTab()
|
function SmartPickupFrame:getRunsForTab()
|
||||||
|
if ADFlowView ~= nil then
|
||||||
|
return ADFlowView.orderedRuns(ADRunsController.store.runs)
|
||||||
|
end
|
||||||
return ADRunsController.store.runs
|
return ADRunsController.store.runs
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -433,28 +437,46 @@ function SmartPickupFrame:fillWaitPoolOption(adEnv, run)
|
|||||||
self.waitPoolOption:setState(index, false)
|
self.waitPoolOption:setState(index, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Traktorer: som standard flowets egne og de ledige der kan bruges; "Vis alle" tilføjer traktorer i andre
|
||||||
|
-- flows og låste (vognen passer ikke) — de er tit mange og gør listen uoverskuelig.
|
||||||
function SmartPickupFrame:fillVehicleRows(adEnv, run)
|
function SmartPickupFrame:fillVehicleRows(adEnv, run)
|
||||||
local inRun = {}
|
local inRun = {}
|
||||||
for _, id in ipairs(run.vehicleIds) do
|
for _, id in ipairs(run.vehicleIds) do
|
||||||
inRun[id] = true
|
inRun[id] = true
|
||||||
end
|
end
|
||||||
|
local entries = {}
|
||||||
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
|
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
|
||||||
local id = ADRunsController.getVehicleId(vehicle)
|
local id = ADRunsController.getVehicleId(vehicle)
|
||||||
|
local otherRun = ADRunsController.getRunForVehicle(vehicle)
|
||||||
|
local state = "free"
|
||||||
|
if inRun[id] then
|
||||||
|
state = "in"
|
||||||
|
elseif otherRun ~= nil and otherRun.id ~= run.id then
|
||||||
|
state = "other"
|
||||||
|
elseif SmartPickupFrame.VEHICLE_BLOCKING_REASONS[ADRunsController.validateVehicle(adEnv, run, vehicle).reason] then
|
||||||
|
state = "blocked"
|
||||||
|
end
|
||||||
|
table.insert(entries, {id = id, label = ADRunsController.getVehicleLabel(adEnv, vehicle), state = state, vehicle = vehicle, otherRun = otherRun})
|
||||||
|
end
|
||||||
|
local rows = ADFlowView.vehicleRows(entries, self.showAllVehicles == true)
|
||||||
|
local hidden = ADFlowView.hiddenCount(entries, rows)
|
||||||
|
if hidden > 0 or self.showAllVehicles then
|
||||||
|
self.showAllVehiclesOption = self:addToggleRow("showAllVehicles", string.format(self.i18n:getText("spu_showAllVehicles"), hidden), {self.i18n:getText("ui_no"), self.i18n:getText("ui_yes")}, self.showAllVehicles == true)
|
||||||
|
end
|
||||||
|
for _, entry in ipairs(rows) do
|
||||||
|
local vehicle = entry.vehicle
|
||||||
local row = self:addRow(self.vehiclePrefab, {kind = "vehicle", vehicle = vehicle, row = nil})
|
local row = self:addRow(self.vehiclePrefab, {kind = "vehicle", vehicle = vehicle, row = nil})
|
||||||
local option, title = row:getDescendantByName("option"), row:getDescendantByName("title")
|
local option, title = row:getDescendantByName("option"), row:getDescendantByName("title")
|
||||||
self.rowData[option].row = row
|
self.rowData[option].row = row
|
||||||
option:setState(inRun[id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
option:setState(entry.state == "in" and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
||||||
-- Traktorer i et ANDET run kan ikke vælges her (én traktor = ét run); rækken viser hvor den er.
|
if entry.state == "other" then
|
||||||
local otherRun = ADRunsController.getRunForVehicle(vehicle)
|
-- én traktor = ét flow; rækken viser hvor den er
|
||||||
if otherRun ~= nil and otherRun.id ~= run.id then
|
|
||||||
option:setDisabled(true)
|
option:setDisabled(true)
|
||||||
self.rowData[option].locked = true
|
self.rowData[option].locked = true
|
||||||
title:setText(string.format("%s — %s", ADRunsController.getVehicleLabel(adEnv, vehicle), string.format(self.i18n:getText("spu_inRun"), tostring(otherRun.name))))
|
title:setText(string.format("%s — %s", entry.label, string.format(self.i18n:getText("spu_inRun"), tostring(entry.otherRun.name))))
|
||||||
else
|
else
|
||||||
title:setText(self:describeVehicle(adEnv, run, vehicle, inRun[id]))
|
title:setText(self:describeVehicle(adEnv, run, vehicle, entry.state == "in"))
|
||||||
-- Vogn der ikke kan bære run'ets varer (ingen vogn / forkert vogn / paller uden UAL) kan ikke
|
if entry.state == "blocked" then
|
||||||
-- vælges; er den allerede i run'et, kan den stadig fravælges.
|
|
||||||
if not inRun[id] and SmartPickupFrame.VEHICLE_BLOCKING_REASONS[ADRunsController.validateVehicle(adEnv, run, vehicle).reason] then
|
|
||||||
option:setDisabled(true)
|
option:setDisabled(true)
|
||||||
self.rowData[option].locked = true
|
self.rowData[option].locked = true
|
||||||
end
|
end
|
||||||
@@ -678,6 +700,11 @@ function SmartPickupFrame:onClickIngredient(state, element)
|
|||||||
return self:onClickCollectRound(state)
|
return self:onClickCollectRound(state)
|
||||||
elseif data ~= nil and data.kind == "direction" then
|
elseif data ~= nil and data.kind == "direction" then
|
||||||
return self:onClickDirection(state)
|
return self:onClickDirection(state)
|
||||||
|
elseif data ~= nil and (data.kind == "showAllVehicles" or data.kind == "showAllBuildings") then
|
||||||
|
local isOn = state == SmartPickupFrame.STATE_ON
|
||||||
|
if data.kind == "showAllVehicles" then self.showAllVehicles = isOn else self.showAllBuildings = isOn end
|
||||||
|
self:requestRebuild()
|
||||||
|
return
|
||||||
elseif data ~= nil and (data.kind == "sourceBuilding" or data.kind == "targetBuilding" or data.kind == "storeBuilding") then
|
elseif data ~= nil and (data.kind == "sourceBuilding" or data.kind == "targetBuilding" or data.kind == "storeBuilding") then
|
||||||
return self:onClickBuilding(state, element)
|
return self:onClickBuilding(state, element)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -135,6 +135,10 @@
|
|||||||
<text name="spu_stat_use" text="forbrug %s/døgn"/>
|
<text name="spu_stat_use" text="forbrug %s/døgn"/>
|
||||||
<text name="spu_stat_prod" text="prod. %s/døgn"/>
|
<text name="spu_stat_prod" text="prod. %s/døgn"/>
|
||||||
<text name="spu_stat_total" text="Bygningen i alt"/>
|
<text name="spu_stat_total" text="Bygningen i alt"/>
|
||||||
|
<text name="spu_board_supply" text="· Ind til bygning ·"/>
|
||||||
|
<text name="spu_board_outbound" text="· Ud fra bygning ·"/>
|
||||||
|
<text name="spu_showAllVehicles" text="Vis alle traktorer (%d skjult)"/>
|
||||||
|
<text name="spu_showAllBuildings" text="Vis alle bygninger (%d skjult uden markør)"/>
|
||||||
<text name="spu_section_store" text="— Lager til (valgfrit; intet valgt = moden vælger selv) —"/>
|
<text name="spu_section_store" text="— Lager til (valgfrit; intet valgt = moden vælger selv) —"/>
|
||||||
<text name="spu_stat_rising" text="stiger"/>
|
<text name="spu_stat_rising" text="stiger"/>
|
||||||
<text name="spu_tab_factories" text="Fabrikker"/>
|
<text name="spu_tab_factories" text="Fabrikker"/>
|
||||||
|
|||||||
@@ -135,6 +135,10 @@
|
|||||||
<text name="spu_stat_use" text="use %s/day"/>
|
<text name="spu_stat_use" text="use %s/day"/>
|
||||||
<text name="spu_stat_prod" text="prod. %s/day"/>
|
<text name="spu_stat_prod" text="prod. %s/day"/>
|
||||||
<text name="spu_stat_total" text="Building total"/>
|
<text name="spu_stat_total" text="Building total"/>
|
||||||
|
<text name="spu_board_supply" text="· Into building ·"/>
|
||||||
|
<text name="spu_board_outbound" text="· Out of building ·"/>
|
||||||
|
<text name="spu_showAllVehicles" text="Show all tractors (%d hidden)"/>
|
||||||
|
<text name="spu_showAllBuildings" text="Show all buildings (%d hidden without marker)"/>
|
||||||
<text name="spu_section_store" text="— Store to (optional; none chosen = the mod picks) —"/>
|
<text name="spu_section_store" text="— Store to (optional; none chosen = the mod picks) —"/>
|
||||||
<text name="spu_stat_rising" text="rising"/>
|
<text name="spu_stat_rising" text="rising"/>
|
||||||
<text name="spu_tab_factories" text="Factories"/>
|
<text name="spu_tab_factories" text="Factories"/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<modDesc descVersion="107">
|
<modDesc descVersion="107">
|
||||||
<author>masterdraco</author>
|
<author>masterdraco</author>
|
||||||
<version>1.18.8.0</version>
|
<version>1.19.0.0</version>
|
||||||
<title>
|
<title>
|
||||||
<en>AD Smart Pickup</en>
|
<en>AD Smart Pickup</en>
|
||||||
</title>
|
</title>
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<sourceFile filename="adPrices.lua"/>
|
<sourceFile filename="adPrices.lua"/>
|
||||||
<sourceFile filename="adOutboundPlanner.lua"/>
|
<sourceFile filename="adOutboundPlanner.lua"/>
|
||||||
<sourceFile filename="adStorageStats.lua"/>
|
<sourceFile filename="adStorageStats.lua"/>
|
||||||
|
<sourceFile filename="adFlowView.lua"/>
|
||||||
<sourceFile filename="adSources.lua"/>
|
<sourceFile filename="adSources.lua"/>
|
||||||
<sourceFile filename="adBuildings.lua"/>
|
<sourceFile filename="adBuildings.lua"/>
|
||||||
<sourceFile filename="adOutbound.lua"/>
|
<sourceFile filename="adOutbound.lua"/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# AD Smart Pickup — brugermanual
|
# AD Smart Pickup — brugermanual
|
||||||
|
|
||||||
Version 1.18.8 · Farming Simulator 25 · tillæg til AutoDrive
|
Version 1.19.0 · Farming Simulator 25 · tillæg til AutoDrive
|
||||||
|
|
||||||
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
||||||
|
|
||||||
@@ -139,7 +139,9 @@ Tryk **ESC** og vælg fanen **Smart Pickup**. Fanen har fem underfaner:
|
|||||||
Foder stald: efter behov · alle siloer → Cow Barn 1 · behov · JCB 1 + JCB 2 · Stoppet (2 traktorer)
|
Foder stald: efter behov · alle siloer → Cow Barn 1 · behov · JCB 1 + JCB 2 · Stoppet (2 traktorer)
|
||||||
```
|
```
|
||||||
|
|
||||||
Linjen læses sådan: **navn: varer · fra → til · regel · traktorer · status**.
|
Linjen læses sådan: **navn: varer · fra → til · regel · traktorer · status**. Tavlen er delt i
|
||||||
|
**Ind til bygning** og **Ud fra bygning**, og hver gruppe er sorteret efter navn. Flow-vælgeren følger
|
||||||
|
samme rækkefølge.
|
||||||
|
|
||||||
- Et `!` efter et bygningsnavn betyder, at bygningen mangler en markør.
|
- Et `!` efter et bygningsnavn betyder, at bygningen mangler en markør.
|
||||||
- `!!` i status er en advarsel, fx at et salgssted ikke kan nås.
|
- `!!` i status er en advarsel, fx at et salgssted ikke kan nås.
|
||||||
@@ -172,7 +174,8 @@ Cow Barn (large) — Cow 1 Milk 6 m · Cow 1 Slurry 4 m
|
|||||||
Silo 7 (silo) — INGEN MARKØR inden for 40 m — sæt en AD-markør ved triggeren
|
Silo 7 (silo) — INGEN MARKØR inden for 40 m — sæt en AD-markør ved triggeren
|
||||||
```
|
```
|
||||||
|
|
||||||
Sæt **Ja** ud for de bygninger, flowet skal bruge. Listen er sorteret efter navn, så *Silo 9*
|
Sæt **Ja** ud for de bygninger, flowet skal bruge. De valgte står øverst. Bygninger uden markør er
|
||||||
|
skjult, indtil du slår **Vis alle bygninger** til. Listen er ellers sorteret efter navn, så *Silo 9*
|
||||||
kommer før *Silo 10*. En bygning, du har solgt, står som *bygningen findes ikke længere*.
|
kommer før *Silo 10*. En bygning, du har solgt, står som *bygningen findes ikke længere*.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -396,6 +399,8 @@ Nederst i flowet står gårdens køretøjer med kapacitet. Sæt **Ja** ud for de
|
|||||||
|
|
||||||
- Kapaciteten står i liter for bulkvogne og som *autoload (paller)* for UAL-vogne.
|
- Kapaciteten står i liter for bulkvogne og som *autoload (paller)* for UAL-vogne.
|
||||||
- **Køretøjer, der ikke kan bruges, er låst** og viser grunden. Grundene er beskrevet i tabellen.
|
- **Køretøjer, der ikke kan bruges, er låst** og viser grunden. Grundene er beskrevet i tabellen.
|
||||||
|
- Som standard vises flowets egne traktorer og de ledige, der kan bruges. Traktorer i andre flows og
|
||||||
|
låste traktorer vises med **Vis alle traktorer**.
|
||||||
- Et køretøj kan kun være med i ét flow. Flyttes det, står der *flyttet fra 'andet flow'*.
|
- Et køretøj kan kun være med i ét flow. Flyttes det, står der *flyttet fra 'andet flow'*.
|
||||||
- Fjerner du en kørende traktor fra et flow, stoppes den.
|
- Fjerner du en kørende traktor fra et flow, stoppes den.
|
||||||
- **Navne:** traktorerne får automatisk AutoDrive-førernavn efter deres flow, fx *Milk Collect 1* og
|
- **Navne:** traktorerne får automatisk AutoDrive-førernavn efter deres flow, fx *Milk Collect 1* og
|
||||||
|
|||||||
+8
-3
@@ -1,6 +1,6 @@
|
|||||||
# AD Smart Pickup — user manual
|
# AD Smart Pickup — user manual
|
||||||
|
|
||||||
Version 1.18.8 · Farming Simulator 25 · add-on for AutoDrive
|
Version 1.19.0 · Farming Simulator 25 · add-on for AutoDrive
|
||||||
|
|
||||||
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
||||||
|
|
||||||
@@ -141,7 +141,9 @@ At the top there is one line per flow. The selected flow is marked with `>`.
|
|||||||
Barn feed: by need · all silos → Cow Barn 1 · need · JCB 1 + JCB 2 · Stopped (2 tractors)
|
Barn feed: by need · all silos → Cow Barn 1 · need · JCB 1 + JCB 2 · Stopped (2 tractors)
|
||||||
```
|
```
|
||||||
|
|
||||||
Read the line as **name: goods · from → to · rule · tractors · status**.
|
Read the line as **name: goods · from → to · rule · tractors · status**. The board is split into
|
||||||
|
**Into building** and **Out of building**, and each group is sorted by name. The flow selector follows
|
||||||
|
the same order.
|
||||||
|
|
||||||
- A `!` after a building name means the building has no marker.
|
- A `!` after a building name means the building has no marker.
|
||||||
- `!!` in the status is a warning, such as a selling point that cannot be reached.
|
- `!!` in the status is a warning, such as a selling point that cannot be reached.
|
||||||
@@ -174,7 +176,8 @@ Cow Barn (large) — Cow 1 Milk 6 m · Cow 1 Slurry 4 m
|
|||||||
Silo 7 (silo) — NO MARKER within 40 m — place an AD marker at the trigger
|
Silo 7 (silo) — NO MARKER within 40 m — place an AD marker at the trigger
|
||||||
```
|
```
|
||||||
|
|
||||||
Set **Yes** on the buildings the flow should use. The list is sorted by name, so *Silo 9* comes
|
Set **Yes** on the buildings the flow should use. The chosen ones are at the top. Buildings without a
|
||||||
|
marker are hidden until you switch on **Show all buildings**. Otherwise the list is sorted by name, so *Silo 9* comes
|
||||||
before *Silo 10*. A building you have sold shows as *building no longer exists*.
|
before *Silo 10*. A building you have sold shows as *building no longer exists*.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -401,6 +404,8 @@ ones that should drive.
|
|||||||
|
|
||||||
- Capacity is shown in litres for bulk trailers and as *autoload (pallets)* for UAL trailers.
|
- Capacity is shown in litres for bulk trailers and as *autoload (pallets)* for UAL trailers.
|
||||||
- **Vehicles that cannot be used are locked** and show the reason. The reasons are in the table.
|
- **Vehicles that cannot be used are locked** and show the reason. The reasons are in the table.
|
||||||
|
- By default the flow's own tractors and the free usable ones are shown. Tractors in other flows and
|
||||||
|
locked tractors appear with **Show all tractors**.
|
||||||
- A vehicle can only be in one flow. If it is moved, it shows *moved from 'other flow'*.
|
- A vehicle can only be in one flow. If it is moved, it shows *moved from 'other flow'*.
|
||||||
- If you remove a running tractor from a flow, it is stopped.
|
- If you remove a running tractor from a flow, it is stopped.
|
||||||
- **Names:** tractors automatically get an AutoDrive driver name after their flow, such as
|
- **Names:** tractors automatically get an AutoDrive driver name after their flow, such as
|
||||||
|
|||||||
@@ -189,8 +189,9 @@ end
|
|||||||
-- B-COOP: hønsehus — foder aflæsses i den ene ende, æg-paller spawnes i den anden (ingen læssestation)
|
-- B-COOP: hønsehus — foder aflæsses i den ene ende, æg-paller spawnes i den anden (ingen læssestation)
|
||||||
do
|
do
|
||||||
local coop = placeable("coop1", "Chicken Coop", 10000, 0, {getHusbandryFillLevel = function() return 0 end,
|
local coop = placeable("coop1", "Chicken Coop", 10000, 0, {getHusbandryFillLevel = function() return 0 end,
|
||||||
|
spec_husbandryFood = {feedingTrough = {exactFillRootNode = {x = 9970, z = 0}}},
|
||||||
spec_husbandryPallets = {fillTypeIndexToPalletSpawner = {[99] = {spawnPlaces = {{startNode = {x = 10030, z = 0}}}}}}})
|
spec_husbandryPallets = {fillTypeIndexToPalletSpawner = {[99] = {spawnPlaces = {{startNode = {x = 10030, z = 0}}}}}}})
|
||||||
table.insert(unloadStations, {owningPlaceable = coop, unloadTriggers = {{exactFillRootNode = {x = 9970, z = 0}}}})
|
table.insert(unloadStations, {owningPlaceable = coop, unloadTriggers = {}}) -- som chickenBarnBig: tom station
|
||||||
addMarker(61, "Chicken Food", "Chicken", 9965, 0)
|
addMarker(61, "Chicken Food", "Chicken", 9965, 0)
|
||||||
addMarker(62, "Egg Pickup", "Chicken", 10035, 0)
|
addMarker(62, "Egg Pickup", "Chicken", 10035, 0)
|
||||||
ADBuildings.invalidate()
|
ADBuildings.invalidate()
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
-- Kør: luajit tests/test_adFlowView.lua (fra repo-roden)
|
||||||
|
-- Ren oprydning af Flows-fanen: tavlens rækkefølge, hvilke traktorer og bygninger der vises.
|
||||||
|
|
||||||
|
dofile("FS25_ADSmartPickup/adFlowView.lua")
|
||||||
|
local V = ADFlowView
|
||||||
|
|
||||||
|
local failures = 0
|
||||||
|
local function check(name, actual, expected)
|
||||||
|
if actual == expected then
|
||||||
|
print("OK " .. name)
|
||||||
|
else
|
||||||
|
failures = failures + 1
|
||||||
|
print(string.format("FAIL %s: forventede %s, fik %s", name, tostring(expected), tostring(actual)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function ids(list, field)
|
||||||
|
local out = {}
|
||||||
|
for _, item in ipairs(list) do table.insert(out, tostring(item[field or "id"])) end
|
||||||
|
return table.concat(out, ",")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- FV1: tavlen — forsyning (Ind) først, så udkørsel (Ud); hver gruppe sorteret efter navn (naturligt)
|
||||||
|
local runs = {
|
||||||
|
{id = 1, name = "Pig Food", kind = "supply"},
|
||||||
|
{id = 2, name = "Milk Sale", kind = "outbound"},
|
||||||
|
{id = 3, name = "Cow Food", kind = "supply"},
|
||||||
|
{id = 4, name = "Biogas 10", kind = "supply"},
|
||||||
|
{id = 5, name = "Biogas 9", kind = "supply"},
|
||||||
|
{id = 6, name = "Digestate", kind = "outbound"},
|
||||||
|
}
|
||||||
|
local groups = V.boardGroups(runs)
|
||||||
|
check("FV1 to grupper", #groups, 2)
|
||||||
|
check("FV1 Ind først", groups[1].kind, "supply")
|
||||||
|
check("FV1 Ind sorteret (Biogas 9 før 10)", ids(groups[1].runs), "5,4,3,1")
|
||||||
|
check("FV1 Ud sorteret", ids(groups[2].runs), "6,2")
|
||||||
|
check("FV1 samlet rækkefølge til vælgeren", ids(V.orderedRuns(runs)), "5,4,3,1,6,2")
|
||||||
|
check("FV1 tom gruppe udelades", #V.boardGroups({{id = 1, name = "A", kind = "supply"}}), 1)
|
||||||
|
|
||||||
|
-- FV2: traktorer — egne først, så ledige brugbare; andre flows og låste kun med "vis alle"
|
||||||
|
local vehicles = {
|
||||||
|
{id = "a", label = "Zetor", state = "free"},
|
||||||
|
{id = "b", label = "Fendt", state = "in"},
|
||||||
|
{id = "c", label = "Case", state = "other"},
|
||||||
|
{id = "d", label = "Claas", state = "blocked"},
|
||||||
|
{id = "e", label = "Deutz", state = "free"},
|
||||||
|
}
|
||||||
|
check("FV2 standard: egne + ledige, sorteret", ids(V.vehicleRows(vehicles, false)), "b,e,a")
|
||||||
|
check("FV2 vis alle: + andre flows + låste til sidst", ids(V.vehicleRows(vehicles, true)), "b,e,a,c,d")
|
||||||
|
check("FV2 antal skjulte", V.hiddenCount(vehicles, V.vehicleRows(vehicles, false)), 2)
|
||||||
|
|
||||||
|
-- FV3: bygninger — valgte først; uden markør skjult medmindre valgt eller "vis alle"
|
||||||
|
local buildings = {
|
||||||
|
{id = "s2", name = "Silo 2", hasMarker = true},
|
||||||
|
{id = "s10", name = "Silo 10", hasMarker = true},
|
||||||
|
{id = "x", name = "Gammel lade", hasMarker = false},
|
||||||
|
{id = "y", name = "Anden uden", hasMarker = false},
|
||||||
|
{id = "a", name = "Anlæg", hasMarker = true},
|
||||||
|
}
|
||||||
|
local chosen = {s10 = true, y = true}
|
||||||
|
check("FV3 standard: valgte først, så med markør", ids(V.buildingRows(buildings, chosen, false)), "y,s10,a,s2")
|
||||||
|
check("FV3 vis alle: uden markør til sidst", ids(V.buildingRows(buildings, chosen, true)), "y,s10,a,s2,x")
|
||||||
|
|
||||||
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
|
os.exit(failures == 0 and 0 or 1)
|
||||||
@@ -1259,5 +1259,22 @@ check("X3 Wait-logik springer udkørsel over", okWait, true)
|
|||||||
FS25_AutoDrive.AutoDrive.getAllDischargeableUnits = originalUnits
|
FS25_AutoDrive.AutoDrive.getAllDischargeableUnits = originalUnits
|
||||||
ADOutbound = nil
|
ADOutbound = nil
|
||||||
|
|
||||||
|
-- FT: hønsehus — foderkrybben (spec_husbandryFood.feedingTrough) står ikke i aflæsningsstationens
|
||||||
|
-- unloadTriggers; stationsopslaget ved markøren skal alligevel finde hønsehuset
|
||||||
|
do
|
||||||
|
local coop = {getHusbandryFillLevel = function() return 0 end, getName = function() return "Chicken Coop" end,
|
||||||
|
spec_husbandryFood = {feedingTrough = {exactFillRootNode = 9901}}}
|
||||||
|
nodePositions[9901] = {x = 20000, z = 3}
|
||||||
|
local coopStation = {owningPlaceable = coop, unloadTriggers = {}}
|
||||||
|
table.insert(unloadStations, coopStation)
|
||||||
|
g_currentMission.placeableSystem = {placeables = {coop}}
|
||||||
|
ADSmartPickup.invalidateUnloadCandidates()
|
||||||
|
addMarker(95, "Chicken 1 food", "Chicken", 20000, 10)
|
||||||
|
local found = ADSmartPickup.getUnloadStationAtWayPointId(FS25_AutoDrive, 95, 1)
|
||||||
|
check("FT krybbe findes via markøren", found ~= nil and found.owningPlaceable == coop, true)
|
||||||
|
g_currentMission.placeableSystem = nil
|
||||||
|
ADSmartPickup.invalidateUnloadCandidates()
|
||||||
|
end
|
||||||
|
|
||||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
os.exit(failures == 0 and 0 or 1)
|
os.exit(failures == 0 and 0 or 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user