feat(navne): egne bygningsnavne fra ADSmartPickup_names.xml bruges overalt (FS25 kan ikke omdøbe bygninger); marksilo: siloer i samme klynge som et gårdlager er gårdens (v1.39.0.0)
This commit is contained in:
@@ -31,6 +31,8 @@ local function getNodePosition(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function getName(placeable, fallback)
|
local function getName(placeable, fallback)
|
||||||
|
local own = ADNames ~= nil and ADNames.forPlaceable(placeable) or nil
|
||||||
|
if own ~= nil then return own end
|
||||||
if placeable ~= nil and placeable.getName ~= nil then
|
if placeable ~= nil and placeable.getName ~= nil then
|
||||||
local ok, name = pcall(placeable.getName, placeable)
|
local ok, name = pcall(placeable.getName, placeable)
|
||||||
if ok and name ~= nil then return tostring(name) end
|
if ok and name ~= nil then return tostring(name) end
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ ADFieldSilos.CARGO_MIN_LITERS = 100 -- rest under dette tæller ikke som last
|
|||||||
-- Silo så tæt på et gårdlager er en del af gården (Farma-siloer deler lager inden for 50 m): ikke marksilo.
|
-- Silo så tæt på et gårdlager er en del af gården (Farma-siloer deler lager inden for 50 m): ikke marksilo.
|
||||||
-- (in-game 27/9: sukkerroer blev kørt fra én Farma-silo til nabosiloen i samme klynge)
|
-- (in-game 27/9: sukkerroer blev kørt fra én Farma-silo til nabosiloen i samme klynge)
|
||||||
ADFieldSilos.FARM_RADIUS = 100
|
ADFieldSilos.FARM_RADIUS = 100
|
||||||
|
-- Siloer højst så langt fra en nabo hører til samme klynge (Farma-rækker: 15 m mellem siloer, 18 m mellem rækker)
|
||||||
|
ADFieldSilos.CLUSTER_LINK = 60
|
||||||
ADFieldSilos.MOVING_SPEED = 0.00028 -- m/ms, samme grænse som AutoDrive
|
ADFieldSilos.MOVING_SPEED = 0.00028 -- m/ms, samme grænse som AutoDrive
|
||||||
ADFieldSilos.FILE_NAME = "ADSmartPickup_fieldsilos.xml"
|
ADFieldSilos.FILE_NAME = "ADSmartPickup_fieldsilos.xml"
|
||||||
ADFieldSilos.ROOT = "ADSmartPickupFieldSilos"
|
ADFieldSilos.ROOT = "ADSmartPickupFieldSilos"
|
||||||
@@ -113,6 +115,26 @@ local function runBuildingIds()
|
|||||||
return ids
|
return ids
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Alle siloer i samme klynge som et gårdlager (kæde af naboer ≤ CLUSTER_LINK): gårdens, aldrig marksiloer.
|
||||||
|
-- (in-game 27/9: gårdens Farma-klynge er ~300 m lang; siloer over 100 m fra et valgt lager blev marksiloer)
|
||||||
|
local function farmCluster(allSilos, storeIds)
|
||||||
|
local farm, queue = {}, {}
|
||||||
|
for _, silo in ipairs(allSilos) do
|
||||||
|
if storeIds[silo.id] then farm[silo.id] = true; table.insert(queue, silo) end
|
||||||
|
end
|
||||||
|
local link2 = ADFieldSilos.CLUSTER_LINK ^ 2
|
||||||
|
while #queue > 0 do
|
||||||
|
local current = table.remove(queue)
|
||||||
|
for _, silo in ipairs(allSilos) do
|
||||||
|
if not farm[silo.id] and (silo.x - current.x) ^ 2 + (silo.z - current.z) ^ 2 <= link2 then
|
||||||
|
farm[silo.id] = true
|
||||||
|
table.insert(queue, silo)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return farm
|
||||||
|
end
|
||||||
|
|
||||||
local function nearStore(stores, x, z)
|
local function nearStore(stores, x, z)
|
||||||
for _, store in ipairs(stores) do
|
for _, store in ipairs(stores) do
|
||||||
if (store.x - x) ^ 2 + (store.z - z) ^ 2 <= ADFieldSilos.FARM_RADIUS ^ 2 then return true end
|
if (store.x - x) ^ 2 + (store.z - z) ^ 2 <= ADFieldSilos.FARM_RADIUS ^ 2 then return true end
|
||||||
@@ -123,9 +145,14 @@ end
|
|||||||
-- Gårdlagre fra opsætningen + marksiloer (alle markers marksiloer, uden dubletter og uden gårdlagre).
|
-- Gårdlagre fra opsætningen + marksiloer (alle markers marksiloer, uden dubletter og uden gårdlagre).
|
||||||
function ADFieldSilos.collectBuildings(adEnv)
|
function ADFieldSilos.collectBuildings(adEnv)
|
||||||
local fid = farmId()
|
local fid = farmId()
|
||||||
local stores, byId = {}, {}
|
local stores, byId, allSilos, storeIds = {}, {}, {}, {}
|
||||||
for _, building in ipairs(ADBuildings.list(adEnv, fid)) do
|
for _, building in ipairs(ADBuildings.list(adEnv, fid)) do
|
||||||
byId[building.id] = building
|
byId[building.id] = building
|
||||||
|
if building.kind == "silo" then
|
||||||
|
local sx, sz = position(building.placeable ~= nil and building.placeable.rootNode or nil)
|
||||||
|
table.insert(allSilos, {id = building.id, x = sx, z = sz})
|
||||||
|
if ADFieldSiloConfig.hasStore(ADFieldSilos.config, building.id) then storeIds[building.id] = true end
|
||||||
|
end
|
||||||
if building.kind == "silo" and ADFieldSiloConfig.hasStore(ADFieldSilos.config, building.id) then
|
if building.kind == "silo" and ADFieldSiloConfig.hasStore(ADFieldSilos.config, building.id) then
|
||||||
local x, z = position(building.placeable ~= nil and building.placeable.rootNode or nil)
|
local x, z = position(building.placeable ~= nil and building.placeable.rootNode or nil)
|
||||||
table.insert(stores, {id = building.id, name = building.name, markerId = firstMarker(building, "unload"),
|
table.insert(stores, {id = building.id, name = building.name, markerId = firstMarker(building, "unload"),
|
||||||
@@ -133,6 +160,7 @@ function ADFieldSilos.collectBuildings(adEnv)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local silos, seen = {}, runBuildingIds()
|
local silos, seen = {}, runBuildingIds()
|
||||||
|
for id in pairs(farmCluster(allSilos, storeIds)) do seen[id] = true end
|
||||||
for _, info in ipairs(ADFields.list()) do
|
for _, info in ipairs(ADFields.list()) do
|
||||||
for _, building in ipairs(ADFields.fieldSilos(adEnv, fid, info)) do
|
for _, building in ipairs(ADFields.fieldSilos(adEnv, fid, info)) do
|
||||||
local x, z = position(building.placeable ~= nil and building.placeable.rootNode or nil)
|
local x, z = position(building.placeable ~= nil and building.placeable.rootNode or nil)
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
-- AD Names
|
||||||
|
-- Egne bygningsnavne (FS25 kan ikke omdøbe bygninger): ADSmartPickup_names.xml i savegame-mappen,
|
||||||
|
-- <ADSmartPickupNames><building id="placeable…" name="Gårdsilo 10"/></ADSmartPickupNames>.
|
||||||
|
-- Moden læser filen og skriver den aldrig — spillerens/Claudes navne overlever. Bruges af alle navneopslag.
|
||||||
|
|
||||||
|
ADNames = {}
|
||||||
|
ADNames.FILE_NAME = "ADSmartPickup_names.xml"
|
||||||
|
ADNames.ROOT = "ADSmartPickupNames"
|
||||||
|
ADNames.byId = nil
|
||||||
|
|
||||||
|
-- records = {{id, name}} -> {[id] = name}; tomme/ugyldige springes over
|
||||||
|
function ADNames.fromRecords(records)
|
||||||
|
local byId = {}
|
||||||
|
for _, record in ipairs(records or {}) do
|
||||||
|
local id, name = record.id, record.name
|
||||||
|
if type(id) == "string" and id ~= "" and type(name) == "string" and name:match("%S") then byId[id] = name end
|
||||||
|
end
|
||||||
|
return byId
|
||||||
|
end
|
||||||
|
|
||||||
|
function ADNames.load()
|
||||||
|
ADNames.byId = {}
|
||||||
|
local path = ADRunsStorage ~= nil and ADRunsStorage.getPath() or nil
|
||||||
|
if path == nil then return end
|
||||||
|
path = path:gsub(ADRunsStorage.FILE_NAME .. "$", ADNames.FILE_NAME)
|
||||||
|
if not fileExists(path) then return end
|
||||||
|
local xmlFile = XMLFile.load("ADSmartPickupNames", path)
|
||||||
|
if xmlFile == nil then return end
|
||||||
|
local records = {}
|
||||||
|
xmlFile:iterate(ADNames.ROOT .. ".building", function(_, key)
|
||||||
|
table.insert(records, {id = xmlFile:getString(key .. "#id"), name = xmlFile:getString(key .. "#name")})
|
||||||
|
end)
|
||||||
|
xmlFile:delete()
|
||||||
|
ADNames.byId = ADNames.fromRecords(records)
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(ADNames.byId) do count = count + 1 end
|
||||||
|
Logging.info("ADSmartPickup: %d egne bygningsnavne indlæst", count)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Eget navn for bygningen (placeable), ellers nil.
|
||||||
|
function ADNames.forPlaceable(placeable)
|
||||||
|
if placeable == nil or placeable.uniqueId == nil then return nil end
|
||||||
|
if ADNames.byId == nil then pcall(ADNames.load) end
|
||||||
|
return (ADNames.byId or {})[tostring(placeable.uniqueId)]
|
||||||
|
end
|
||||||
@@ -1333,6 +1333,7 @@ function ADRunsController.load(adEnv)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
ADRunsController.store = store
|
ADRunsController.store = store
|
||||||
|
if ADNames ~= nil then pcall(ADNames.load) end
|
||||||
pcall(ADRunsController.migrateBuildings, adEnv)
|
pcall(ADRunsController.migrateBuildings, adEnv)
|
||||||
if ADFieldSilos ~= nil then pcall(ADFieldSilos.load) end
|
if ADFieldSilos ~= nil then pcall(ADFieldSilos.load) end
|
||||||
local vehiclesById = getFarmVehiclesById(adEnv)
|
local vehiclesById = getFarmVehiclesById(adEnv)
|
||||||
|
|||||||
@@ -471,7 +471,7 @@ end
|
|||||||
local factoryFallbackLogged = setmetatable({}, {__mode = "k"})
|
local factoryFallbackLogged = setmetatable({}, {__mode = "k"})
|
||||||
local function logFactoryFallbackOnce(driver, station)
|
local function logFactoryFallbackOnce(driver, station)
|
||||||
local placeable = station.owningPlaceable
|
local placeable = station.owningPlaceable
|
||||||
local name = placeable ~= nil and placeable.getName ~= nil and placeable:getName() or "fabrik"
|
local name = (ADNames ~= nil and ADNames.forPlaceable(placeable)) or (placeable ~= nil and placeable.getName ~= nil and placeable:getName()) or "fabrik"
|
||||||
local message = string.format("'%s': %s har ingen ønskede produktioner (tændte eller auto-slukkede pga. mangel) med varer vognen kan bære; bruger dit varevalg", tostring(ADRuns.vehicleLabel(driver)), tostring(name))
|
local message = string.format("'%s': %s har ingen ønskede produktioner (tændte eller auto-slukkede pga. mangel) med varer vognen kan bære; bruger dit varevalg", tostring(ADRuns.vehicleLabel(driver)), tostring(name))
|
||||||
if factoryFallbackLogged[driver] ~= message then
|
if factoryFallbackLogged[driver] ~= message then
|
||||||
factoryFallbackLogged[driver] = message
|
factoryFallbackLogged[driver] = message
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ local function getNodePosition(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function getPlaceableName(placeable, fallback)
|
local function getPlaceableName(placeable, fallback)
|
||||||
|
local own = ADNames ~= nil and ADNames.forPlaceable(placeable) or nil
|
||||||
|
if own ~= nil then return own end
|
||||||
if placeable ~= nil and placeable.getName ~= nil then
|
if placeable ~= nil and placeable.getName ~= nil then
|
||||||
local ok, name = pcall(placeable.getName, placeable)
|
local ok, name = pcall(placeable.getName, placeable)
|
||||||
if ok and name ~= nil then
|
if ok and name ~= nil then
|
||||||
|
|||||||
@@ -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.38.7.0</version>
|
<version>1.39.0.0</version>
|
||||||
<title>
|
<title>
|
||||||
<en>AD Smart Pickup</en>
|
<en>AD Smart Pickup</en>
|
||||||
</title>
|
</title>
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
<l10n filenamePrefix="l10n/l10n"/>
|
<l10n filenamePrefix="l10n/l10n"/>
|
||||||
<extraSourceFiles>
|
<extraSourceFiles>
|
||||||
<sourceFile filename="adCache.lua"/>
|
<sourceFile filename="adCache.lua"/>
|
||||||
|
<sourceFile filename="adNames.lua"/>
|
||||||
<sourceFile filename="adStuckDiag.lua"/>
|
<sourceFile filename="adStuckDiag.lua"/>
|
||||||
<sourceFile filename="adSupplyPlanner.lua"/>
|
<sourceFile filename="adSupplyPlanner.lua"/>
|
||||||
<sourceFile filename="adRuns.lua"/>
|
<sourceFile filename="adRuns.lua"/>
|
||||||
|
|||||||
@@ -125,6 +125,18 @@ do
|
|||||||
check("gårdens nabosilo (40 m fra gårdlager) er ikke marksilo", table.concat(names, ","), "fs")
|
check("gårdens nabosilo (40 m fra gårdlager) er ikke marksilo", table.concat(names, ","), "fs")
|
||||||
ADFields.fieldSilos = function() return {fieldSilo, farm} end
|
ADFields.fieldSilos = function() return {fieldSilo, farm} end
|
||||||
|
|
||||||
|
-- in-game 27/9: gårdens Farma-klynge er 300 m lang — siloer over 100 m fra et valgt gårdlager blev marksiloer.
|
||||||
|
-- En silo i samme klynge (≤ 60 m til en nabo) som et gårdlager er gårdens.
|
||||||
|
local c1 = {id = "c1", name = "Klynge 1", kind = "silo", placeable = {rootNode = {x = 50, z = 0}, spec_silo = {storages = {storage({[WHEAT] = 60000}, 0)}}}}
|
||||||
|
local c2 = {id = "c2", name = "Klynge 2", kind = "silo", placeable = {rootNode = {x = 105, z = 0}, spec_silo = {storages = {storage({[WHEAT] = 60000}, 0)}}}}
|
||||||
|
ADBuildings.list = function() return {fieldSilo, farm, c1, c2} end
|
||||||
|
ADFields.fieldSilos = function() return {fieldSilo, farm, c1, c2} end
|
||||||
|
local clustered = {}
|
||||||
|
for _, silo in ipairs(S.collectBuildings(adEnv)) do table.insert(clustered, silo.id) end
|
||||||
|
check("gårdens klynge (105 m via nabo) er ikke marksilo", table.concat(clustered, ","), "fs")
|
||||||
|
ADBuildings.list = function() return {fieldSilo, farm} end
|
||||||
|
ADFields.fieldSilos = function() return {fieldSilo, farm} end
|
||||||
|
|
||||||
-- M5: rest under 100 l tæller ikke som last
|
-- M5: rest under 100 l tæller ikke som last
|
||||||
residue = 50
|
residue = 50
|
||||||
local vehicles = S.collectVehicles(adEnv)
|
local vehicles = S.collectVehicles(adEnv)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
-- Kør: luajit tests/test_adNames.lua (fra repo-roden)
|
||||||
|
dofile("FS25_ADSmartPickup/adNames.lua")
|
||||||
|
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 byId = ADNames.fromRecords({{id = "placeableA", name = "Gårdsilo 10"}, {id = "", name = "x"}, {id = "placeableB", name = " "}, {id = "placeableC"}})
|
||||||
|
check("navn indlæst", byId.placeableA, "Gårdsilo 10")
|
||||||
|
check("tomt id springes over", byId[""], nil)
|
||||||
|
check("blankt navn springes over", byId.placeableB, nil)
|
||||||
|
check("manglende navn springes over", byId.placeableC, nil)
|
||||||
|
ADNames.byId = byId
|
||||||
|
check("opslag på bygning", ADNames.forPlaceable({uniqueId = "placeableA"}), "Gårdsilo 10")
|
||||||
|
check("bygning uden eget navn", ADNames.forPlaceable({uniqueId = "placeableZ"}), nil)
|
||||||
|
check("uden uniqueId", ADNames.forPlaceable({}), nil)
|
||||||
|
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