fix(kæde): spillerens slukninger huskes, pause beskytter kun sin egen kæde, stoppede flows slippes og forældede nøgler glemmes
This commit is contained in:
+116
-22
@@ -1,8 +1,9 @@
|
|||||||
-- AD Chain (kæde-kørsel)
|
-- AD Chain (kæde-kørsel)
|
||||||
-- Hvert minut (efter opstartsfristen): læs gården (ADChainData), byg kæden (ADChainModel), find manglende
|
-- Hvert minut (efter opstartsfristen): læs gården (ADChainData), byg kæden (ADChainModel), find manglende
|
||||||
-- afgrøder (ADCropPlan) og lad ADChainRun skifte frie marker, tænde/slukke mellemled og oprette/stoppe flows.
|
-- afgrøder (ADCropPlan) og lad ADChainRun skifte frie marker, tænde/slukke mellemled og oprette/stoppe flows.
|
||||||
-- Resultatet gemmes i ADChain.last til Kæder-fanen. Tilstanden (byChain, pausede rødder, afviste forslag)
|
-- Resultatet gemmes i ADChain.last til Kæder-fanen. Tilstanden (byChain, pausede rødder, afviste forslag,
|
||||||
-- gemmes i ADSmartPickup_chain.xml under spillets gem. Spiladgang kun inde i funktioner (filen dofile's i test).
|
-- userOff og det sidst kendte sæt af rødder) gemmes i ADSmartPickup_chain.xml under spillets gem.
|
||||||
|
-- Spiladgang kun inde i funktioner (filen dofile's i test).
|
||||||
|
|
||||||
ADChain = {}
|
ADChain = {}
|
||||||
ADChain.FILE_NAME = "ADSmartPickup_chain.xml"
|
ADChain.FILE_NAME = "ADSmartPickup_chain.xml"
|
||||||
@@ -17,6 +18,10 @@ ADChain.DISMISS_CHANGE = 0.25
|
|||||||
|
|
||||||
ADChain.state = {byChain = {}, paused = {}, dismissed = {}, userOff = {}}
|
ADChain.state = {byChain = {}, paused = {}, dismissed = {}, userOff = {}}
|
||||||
ADChain.last = nil
|
ADChain.last = nil
|
||||||
|
-- {[nøgle] = true}: produktioner (ikke kædens) der var tændt ved sidste tick — til at se spillerens slukninger
|
||||||
|
ADChain.prevEnabled = nil
|
||||||
|
-- true fra indlæsning til første tick: kædens produktioner der er slukket, glemmes (spillet blev ikke gemt)
|
||||||
|
ADChain.afterLoad = false
|
||||||
-- run-id -> true: flows kæden oprettede stoppet, fordi der ikke var traktor/vogn (kun i hukommelsen)
|
-- run-id -> true: flows kæden oprettede stoppet, fordi der ikke var traktor/vogn (kun i hukommelsen)
|
||||||
ADChain.noVehicle = {}
|
ADChain.noVehicle = {}
|
||||||
ADChain.switchCount = 0
|
ADChain.switchCount = 0
|
||||||
@@ -39,12 +44,14 @@ end
|
|||||||
-- ---- rene hjælpere ----
|
-- ---- rene hjælpere ----
|
||||||
|
|
||||||
-- userOff = {[recipeKey] = true}: produktioner spilleren slukkede selv — kæden tænder dem ikke igen.
|
-- userOff = {[recipeKey] = true}: produktioner spilleren slukkede selv — kæden tænder dem ikke igen.
|
||||||
|
-- roots = {[recipeKey] = true} rødderne ved sidste tick (nil = ukendt, fx gem fra en ældre version).
|
||||||
function ADChain.newState()
|
function ADChain.newState()
|
||||||
return {byChain = {}, paused = {}, dismissed = {}, userOff = {}}
|
return {byChain = {}, paused = {}, dismissed = {}, userOff = {}, roots = nil}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ADChain.stateToRecords(state)
|
function ADChain.stateToRecords(state)
|
||||||
local records = {byChain = sortedKeys(state.byChain), paused = sortedKeys(state.paused), userOff = sortedKeys(state.userOff), dismissed = {}}
|
local records = {byChain = sortedKeys(state.byChain), paused = sortedKeys(state.paused), userOff = sortedKeys(state.userOff), dismissed = {},
|
||||||
|
roots = state.roots ~= nil and sortedKeys(state.roots) or nil}
|
||||||
local ids = {}
|
local ids = {}
|
||||||
for id in pairs(state.dismissed or {}) do table.insert(ids, id) end
|
for id in pairs(state.dismissed or {}) do table.insert(ids, id) end
|
||||||
table.sort(ids)
|
table.sort(ids)
|
||||||
@@ -61,6 +68,10 @@ function ADChain.stateFromRecords(records)
|
|||||||
for _, key in ipairs(records.byChain or {}) do state.byChain[key] = true end
|
for _, key in ipairs(records.byChain or {}) do state.byChain[key] = true end
|
||||||
for _, key in ipairs(records.paused or {}) do state.paused[key] = true end
|
for _, key in ipairs(records.paused or {}) do state.paused[key] = true end
|
||||||
for _, key in ipairs(records.userOff or {}) do state.userOff[key] = true end
|
for _, key in ipairs(records.userOff or {}) do state.userOff[key] = true end
|
||||||
|
if records.roots ~= nil then
|
||||||
|
state.roots = {}
|
||||||
|
for _, key in ipairs(records.roots) do state.roots[key] = true end
|
||||||
|
end
|
||||||
for _, entry in ipairs(records.dismissed or {}) do
|
for _, entry in ipairs(records.dismissed or {}) do
|
||||||
local id = tonumber(entry.id)
|
local id = tonumber(entry.id)
|
||||||
if id ~= nil and entry.fruit ~= nil and entry.fruit ~= "" then
|
if id ~= nil and entry.fruit ~= nil and entry.fruit ~= "" then
|
||||||
@@ -99,35 +110,81 @@ function ADChain.unionFruits(usedFruits, fieldDemand)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Kopi af opskrifterne hvor pausede rødder er slukket (så de ikke skaber nye behov).
|
-- Modellens kopi af opskrifterne: pausede rødder markeres paused (kører for sig selv, men skaber intet nyt), og
|
||||||
function ADChain.recipesWithPaused(recipes, paused)
|
-- slukkede userOff-produktioner får 0 cyklusser (de dækker intet behov). Originalerne røres ikke.
|
||||||
|
function ADChain.modelRecipes(recipes, paused, userOff)
|
||||||
local result = {}
|
local result = {}
|
||||||
for index, recipe in ipairs(recipes or {}) do
|
for index, recipe in ipairs(recipes or {}) do
|
||||||
local copy = {}
|
local copy = {}
|
||||||
for key, value in pairs(recipe) do copy[key] = value end
|
for key, value in pairs(recipe) do copy[key] = value end
|
||||||
if (paused or {})[recipe.key] then copy.enabled = false end
|
if (paused or {})[recipe.key] then copy.paused = true end
|
||||||
|
if (userOff or {})[recipe.key] and not recipe.enabled then copy.cyclesPerMonth = 0 end
|
||||||
result[index] = copy
|
result[index] = copy
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Spillerens eget valg: en produktion kæden tændte (byChain) som er slukket, selv om kæden stadig har brug for
|
local function copySet(map)
|
||||||
-- den, er slukket af spilleren (eller tændingen virkede ikke) -> userOff. En nøgle ryddes fra userOff, når kæden
|
local result = {}
|
||||||
-- ikke længere har brug for den (men ikke på delvise data). -> {userOff = ny tabel, added = {nye nøgler}}
|
for key, value in pairs(map or {}) do result[key] = value end
|
||||||
function ADChain.playerOverrides(recipes, needRecipes, userOff, isPartial)
|
return result
|
||||||
local result, added = {}, {}
|
|
||||||
for key in pairs(userOff or {}) do
|
|
||||||
if isPartial or ((needRecipes or {})[key] or 0) > 0 then result[key] = true end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Tændte produktioner der ikke er kædens (= rødderne, inkl. pausede).
|
||||||
|
function ADChain.enabledKeys(recipes)
|
||||||
|
local result = {}
|
||||||
for _, recipe in ipairs(recipes or {}) do
|
for _, recipe in ipairs(recipes or {}) do
|
||||||
local needed = ((needRecipes or {})[recipe.key] or 0) > 0
|
if recipe.enabled and not recipe.byChain then result[recipe.key] = true end
|
||||||
if recipe.byChain and not recipe.enabled and needed and not result[recipe.key] then
|
end
|
||||||
result[recipe.key] = true
|
return result
|
||||||
table.insert(added, recipe.key)
|
end
|
||||||
|
|
||||||
|
-- Spillerens valg og forældede nøgler, før kæden regner (rent: state røres ikke).
|
||||||
|
-- opts = {prevEnabled, isPartial, firstEval}. -> {userOff, byChain, paused, roots, added, forgotten, droppedPaused, cleared}
|
||||||
|
-- * kædens produktion er slukket: af spilleren -> userOff (added); første tick efter indlæsning -> glemt (forgotten)
|
||||||
|
-- * en produktion (ikke kædens) der var tændt sidste tick, er slukket -> userOff (added)
|
||||||
|
-- * userOff ryddes kun når der kommer en ny rod (spilleren tænder noget) — ikke når noget "ikke længere bruges"
|
||||||
|
-- (det gav tænd/sluk-løkker); nye slukninger i samme tick beholdes
|
||||||
|
-- * pausede nøgler for produktioner der er væk eller slukket, droppes (droppedPaused)
|
||||||
|
-- Delvise data: userOff ryddes ikke, rødderne opdateres ikke og pausede droppes ikke.
|
||||||
|
function ADChain.reconcile(state, recipes, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local roots = ADChain.enabledKeys(recipes)
|
||||||
|
local rootAdded = false
|
||||||
|
if state.roots ~= nil then
|
||||||
|
for key in pairs(roots) do if not state.roots[key] then rootAdded = true end end
|
||||||
|
end
|
||||||
|
local result = {userOff = copySet(state.userOff), byChain = copySet(state.byChain), paused = copySet(state.paused),
|
||||||
|
roots = opts.isPartial and state.roots or roots, added = {}, forgotten = {}, droppedPaused = {}, cleared = false}
|
||||||
|
if rootAdded and not opts.isPartial and next(result.userOff) ~= nil then
|
||||||
|
result.userOff, result.cleared = {}, true
|
||||||
|
end
|
||||||
|
local present = {}
|
||||||
|
for _, recipe in ipairs(recipes or {}) do
|
||||||
|
present[recipe.key] = recipe
|
||||||
|
if not recipe.enabled and recipe.byChain then
|
||||||
|
result.byChain[recipe.key] = nil
|
||||||
|
if opts.firstEval then
|
||||||
|
table.insert(result.forgotten, recipe.key)
|
||||||
|
elseif not result.userOff[recipe.key] then
|
||||||
|
result.userOff[recipe.key] = true
|
||||||
|
table.insert(result.added, recipe.key)
|
||||||
|
end
|
||||||
|
elseif not recipe.enabled and (opts.prevEnabled or {})[recipe.key] and not result.userOff[recipe.key] then
|
||||||
|
result.userOff[recipe.key] = true
|
||||||
|
table.insert(result.added, recipe.key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(added)
|
if not opts.isPartial then
|
||||||
return {userOff = result, added = added}
|
for key in pairs(state.paused or {}) do
|
||||||
|
if present[key] == nil or not present[key].enabled then
|
||||||
|
result.paused[key] = nil
|
||||||
|
table.insert(result.droppedPaused, key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(result.added); table.sort(result.forgotten); table.sort(result.droppedPaused)
|
||||||
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Rødder hvis flows ikke må stoppes: kædens aktuelle rødder + pausede rødder (pause rører intet).
|
-- Rødder hvis flows ikke må stoppes: kædens aktuelle rødder + pausede rødder (pause rører intet).
|
||||||
@@ -205,17 +262,37 @@ local function farmId()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function plan(data, state)
|
local function plan(data, state)
|
||||||
local recipes = ADChain.recipesWithPaused(data.recipes, state.paused)
|
local recipes = ADChain.modelRecipes(data.recipes, state.paused, state.userOff)
|
||||||
local chain = ADChainModel.build(recipes, data.husbandry, data.crops)
|
local chain = ADChainModel.build(recipes, data.husbandry, data.crops)
|
||||||
|
-- pausede rødder: det de bruger, er beskyttet mod slukning (modellen regnet som om de ikke var pauset)
|
||||||
|
local protected = {}
|
||||||
|
if next(state.paused) ~= nil then
|
||||||
|
protected = ADChainModel.build(ADChain.modelRecipes(data.recipes, {}, state.userOff), data.husbandry, data.crops).needRecipes
|
||||||
|
end
|
||||||
local used = ADChain.unionFruits(data.usedFruits, chain.fieldDemand)
|
local used = ADChain.unionFruits(data.usedFruits, chain.fieldDemand)
|
||||||
local shortages = ADCropPlan.shortages(chain.fieldDemand, data.stock, data.fields, data.yields)
|
local shortages = ADCropPlan.shortages(chain.fieldDemand, data.stock, data.fields, data.yields)
|
||||||
state.dismissed = ADChain.pruneDismissed(state.dismissed, shortages)
|
state.dismissed = ADChain.pruneDismissed(state.dismissed, shortages)
|
||||||
local actions = ADCropPlan.choose(shortages, data.fields, used, data.yields, data.prices, ADChain.dismissedFruits(state.dismissed))
|
local actions = ADCropPlan.choose(shortages, data.fields, used, data.yields, data.prices, ADChain.dismissedFruits(state.dismissed))
|
||||||
-- de ægte opskrifter (ikke kopien): en pauset rod er stadig tændt og må ikke "tændes" og overtages af kæden
|
-- de ægte opskrifter (ikke kopien): en pauset rod er stadig tændt og må ikke "tændes" og overtages af kæden
|
||||||
local prod = ADChainActions.productions(data.recipes, chain.needRecipes, next(state.paused) ~= nil)
|
local prod = ADChainActions.productions(data.recipes, chain.needRecipes, protected)
|
||||||
return {chain = chain, shortages = shortages, actions = actions, prod = prod, edges = ADChainActions.edges(chain)}
|
return {chain = chain, shortages = shortages, actions = actions, prod = prod, edges = ADChainActions.edges(chain)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function logInfo(fmt, ...) Logging.info(ADChain.LOG_PREFIX .. fmt, ...) end
|
||||||
|
|
||||||
|
-- Spillerens valg og forældede nøgler ind i tilstanden (kun ved tick, før der regnes).
|
||||||
|
local function applyReconcile(state, data)
|
||||||
|
local result = ADChain.reconcile(state, data.recipes, {prevEnabled = ADChain.prevEnabled, isPartial = data.partial == true,
|
||||||
|
firstEval = ADChain.afterLoad})
|
||||||
|
if result.cleared then logInfo("ny produktion tændt — slukkede produktioner må bruges igen") end
|
||||||
|
for _, key in ipairs(result.added) do logInfo("spilleren slukkede %s — kæden tænder den ikke igen", key) end
|
||||||
|
for _, key in ipairs(result.forgotten) do logInfo("kæden glemmer %s (ikke tændt efter indlæsning)", key) end
|
||||||
|
for _, key in ipairs(result.droppedPaused) do logInfo("pause for %s fjernet: produktionen er væk eller slukket", key) end
|
||||||
|
state.userOff, state.byChain, state.paused, state.roots = result.userOff, result.byChain, result.paused, result.roots
|
||||||
|
ADChain.prevEnabled = ADChain.enabledKeys(data.recipes)
|
||||||
|
ADChain.afterLoad = false
|
||||||
|
end
|
||||||
|
|
||||||
-- act = true: udfør handlingerne (tick). Uden act kun en frisk visning (GUI).
|
-- act = true: udfør handlingerne (tick). Uden act kun en frisk visning (GUI).
|
||||||
function ADChain.evaluate(adEnv, act)
|
function ADChain.evaluate(adEnv, act)
|
||||||
local state = ADChain.state
|
local state = ADChain.state
|
||||||
@@ -226,6 +303,10 @@ function ADChain.evaluate(adEnv, act)
|
|||||||
return ADChain.last
|
return ADChain.last
|
||||||
end
|
end
|
||||||
ADChain.collectFailed = false
|
ADChain.collectFailed = false
|
||||||
|
if act then
|
||||||
|
local okState, errState = pcall(applyReconcile, state, data)
|
||||||
|
if not okState then Logging.warning(ADChain.LOG_PREFIX .. "tilstanden kunne ikke opdateres: %s", tostring(errState)) end
|
||||||
|
end
|
||||||
local okPlan, result = pcall(plan, data, state)
|
local okPlan, result = pcall(plan, data, state)
|
||||||
if not okPlan then
|
if not okPlan then
|
||||||
Logging.warning(ADChain.LOG_PREFIX .. "kæden kunne ikke beregnes: %s", tostring(result))
|
Logging.warning(ADChain.LOG_PREFIX .. "kæden kunne ikke beregnes: %s", tostring(result))
|
||||||
@@ -321,6 +402,12 @@ function ADChain.save()
|
|||||||
for index, key in ipairs(records.userOff) do
|
for index, key in ipairs(records.userOff) do
|
||||||
xmlFile:setString(string.format("%s.userOff.recipe(%d)#key", ADChain.ROOT, index - 1), key)
|
xmlFile:setString(string.format("%s.userOff.recipe(%d)#key", ADChain.ROOT, index - 1), key)
|
||||||
end
|
end
|
||||||
|
if records.roots ~= nil then
|
||||||
|
xmlFile:setBool(ADChain.ROOT .. ".roots#known", true)
|
||||||
|
for index, key in ipairs(records.roots) do
|
||||||
|
xmlFile:setString(string.format("%s.roots.recipe(%d)#key", ADChain.ROOT, index - 1), key)
|
||||||
|
end
|
||||||
|
end
|
||||||
for index, entry in ipairs(records.dismissed) do
|
for index, entry in ipairs(records.dismissed) do
|
||||||
local key = string.format("%s.dismissed.field(%d)", ADChain.ROOT, index - 1)
|
local key = string.format("%s.dismissed.field(%d)", ADChain.ROOT, index - 1)
|
||||||
xmlFile:setInt(key .. "#id", entry.id)
|
xmlFile:setInt(key .. "#id", entry.id)
|
||||||
@@ -335,6 +422,7 @@ end
|
|||||||
function ADChain.load()
|
function ADChain.load()
|
||||||
ADChain.state = ADChain.newState()
|
ADChain.state = ADChain.newState()
|
||||||
ADChain.noVehicle = {}
|
ADChain.noVehicle = {}
|
||||||
|
ADChain.prevEnabled, ADChain.afterLoad = nil, true
|
||||||
local path = getPath()
|
local path = getPath()
|
||||||
if path == nil or not fileExists(path) then return end
|
if path == nil or not fileExists(path) then return end
|
||||||
local xmlFile = XMLFile.load("ADSmartPickupChain", path)
|
local xmlFile = XMLFile.load("ADSmartPickupChain", path)
|
||||||
@@ -349,6 +437,12 @@ function ADChain.load()
|
|||||||
xmlFile:iterate(ADChain.ROOT .. ".userOff.recipe", function(_, key)
|
xmlFile:iterate(ADChain.ROOT .. ".userOff.recipe", function(_, key)
|
||||||
table.insert(records.userOff, xmlFile:getString(key .. "#key"))
|
table.insert(records.userOff, xmlFile:getString(key .. "#key"))
|
||||||
end)
|
end)
|
||||||
|
if xmlFile:getBool(ADChain.ROOT .. ".roots#known", false) then
|
||||||
|
records.roots = {}
|
||||||
|
xmlFile:iterate(ADChain.ROOT .. ".roots.recipe", function(_, key)
|
||||||
|
table.insert(records.roots, xmlFile:getString(key .. "#key"))
|
||||||
|
end)
|
||||||
|
end
|
||||||
xmlFile:iterate(ADChain.ROOT .. ".dismissed.field", function(_, key)
|
xmlFile:iterate(ADChain.ROOT .. ".dismissed.field", function(_, key)
|
||||||
table.insert(records.dismissed, {id = xmlFile:getInt(key .. "#id"), fruit = xmlFile:getString(key .. "#fruit"),
|
table.insert(records.dismissed, {id = xmlFile:getInt(key .. "#id"), fruit = xmlFile:getString(key .. "#fruit"),
|
||||||
missingHa = tonumber(xmlFile:getString(key .. "#missingHa"))})
|
missingHa = tonumber(xmlFile:getString(key .. "#missingHa"))})
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
ADChainActions = {}
|
ADChainActions = {}
|
||||||
|
|
||||||
function ADChainActions.productions(recipes, needRecipes, anyPaused)
|
-- protected = {[nøgle] = cyklusser}: behov fra pausede rødder — slukkes ikke, men tændes heller ikke.
|
||||||
|
function ADChainActions.productions(recipes, needRecipes, protected)
|
||||||
local result = {enable = {}, disable = {}}
|
local result = {enable = {}, disable = {}}
|
||||||
for _, recipe in ipairs(recipes or {}) do
|
for _, recipe in ipairs(recipes or {}) do
|
||||||
local needed = ((needRecipes or {})[recipe.key] or 0) > 0
|
local needed = ((needRecipes or {})[recipe.key] or 0) > 0
|
||||||
|
local kept = ((protected or {})[recipe.key] or 0) > 0
|
||||||
if needed and not recipe.enabled then table.insert(result.enable, recipe.key) end
|
if needed and not recipe.enabled then table.insert(result.enable, recipe.key) end
|
||||||
if not needed and recipe.enabled and recipe.byChain and not anyPaused then table.insert(result.disable, recipe.key) end
|
if not needed and not kept and recipe.enabled and recipe.byChain then table.insert(result.disable, recipe.key) end
|
||||||
end
|
end
|
||||||
table.sort(result.enable); table.sort(result.disable)
|
table.sort(result.enable); table.sort(result.disable)
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -52,11 +52,12 @@ function ADChainModel.build(recipes, husbandry, crops)
|
|||||||
local producers, herds = indexProducers(recipes), indexHerds(husbandry)
|
local producers, herds = indexProducers(recipes), indexHerds(husbandry)
|
||||||
-- Rødderne kører for sig selv med fuld fart: deres egne input kræves af deres eget træ. Som leverandør til en
|
-- Rødderne kører for sig selv med fuld fart: deres egne input kræves af deres eget træ. Som leverandør til en
|
||||||
-- anden rod har de derfor fuld kapacitet, men deres input regnes ikke med igen (standalone = ingen rekursion).
|
-- anden rod har de derfor fuld kapacitet, men deres input regnes ikke med igen (standalone = ingen rekursion).
|
||||||
|
-- En pauset rod (recipe.paused) kører også for sig selv, men er ikke rod: kæden skaber intet nyt for den.
|
||||||
local capacity, roots, standalone = {}, {}, {}
|
local capacity, roots, standalone = {}, {}, {}
|
||||||
for _, recipe in ipairs(recipes or {}) do
|
for _, recipe in ipairs(recipes or {}) do
|
||||||
capacity[recipe.key] = recipe.cyclesPerMonth or 0
|
capacity[recipe.key] = recipe.cyclesPerMonth or 0
|
||||||
if recipe.enabled and not recipe.byChain then
|
if recipe.enabled and not recipe.byChain then
|
||||||
table.insert(roots, recipe)
|
if not recipe.paused then table.insert(roots, recipe) end
|
||||||
standalone[recipe.key] = true
|
standalone[recipe.key] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -85,16 +85,11 @@ local function setProduction(data, key, isOn)
|
|||||||
return ok
|
return ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Spillerens slukninger er allerede lagt i state.userOff (ADChain.reconcile før planen): de tændes ikke igen.
|
||||||
-- Delvise data: intet slukkes (en rod der ikke kunne læses, ligner en rod der er slået fra).
|
-- Delvise data: intet slukkes (en rod der ikke kunne læses, ligner en rod der er slået fra).
|
||||||
function ADChainRun.toggleProductions(data, prod, needRecipes)
|
function ADChainRun.toggleProductions(data, prod)
|
||||||
local state = ADChain.state
|
local state = ADChain.state
|
||||||
local byChain = state.byChain
|
local byChain = state.byChain
|
||||||
local overrides = ADChain.playerOverrides(data.recipes, needRecipes, state.userOff, data.partial == true)
|
|
||||||
state.userOff = overrides.userOff
|
|
||||||
for _, key in ipairs(overrides.added) do
|
|
||||||
byChain[key] = nil
|
|
||||||
log("spilleren slukkede %s — kæden tænder den ikke igen", key)
|
|
||||||
end
|
|
||||||
for _, key in ipairs(prod.enable or {}) do
|
for _, key in ipairs(prod.enable or {}) do
|
||||||
if not state.userOff[key] and setProduction(data, key, true) then
|
if not state.userOff[key] and setProduction(data, key, true) then
|
||||||
byChain[key] = true
|
byChain[key] = true
|
||||||
@@ -175,7 +170,8 @@ function ADChainRun.createFlows(adEnv, data, edges)
|
|||||||
return count
|
return count
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Flows for rødder der er slået fra: flyt til en anden rod der stadig bruger kanten, ellers stop (slettes ikke).
|
-- Flows for rødder der er slået fra: flyt til en anden rod der stadig bruger kanten, ellers stop og slip (chain
|
||||||
|
-- ryddes, så spilleren kan starte flowet igen uden at kæden stopper det næste minut; det slettes ikke).
|
||||||
function ADChainRun.stopFlows(adEnv, chain, edges)
|
function ADChainRun.stopFlows(adEnv, chain, edges)
|
||||||
local changed = 0
|
local changed = 0
|
||||||
local active = ADChain.activeRoots(chain, ADChain.state.paused)
|
local active = ADChain.activeRoots(chain, ADChain.state.paused)
|
||||||
@@ -188,7 +184,8 @@ function ADChainRun.stopFlows(adEnv, chain, edges)
|
|||||||
else
|
else
|
||||||
local ok, err = pcall(ADRunsController.stopRun, adEnv, run.id)
|
local ok, err = pcall(ADRunsController.stopRun, adEnv, run.id)
|
||||||
if ok then
|
if ok then
|
||||||
log("flow '%s' stoppet: kæden %s er slået fra", tostring(run.name), tostring(run.chain))
|
ADRunsController.updateRun(run.id, {chain = ""})
|
||||||
|
log("flow '%s' stoppet og sluppet af kæden: kæden %s er slået fra", tostring(run.name), tostring(run.chain))
|
||||||
changed = changed + 1
|
changed = changed + 1
|
||||||
else
|
else
|
||||||
warn("flow '%s' kunne ikke stoppes: %s", tostring(run.name), tostring(err))
|
warn("flow '%s' kunne ikke stoppes: %s", tostring(run.name), tostring(err))
|
||||||
@@ -202,7 +199,7 @@ end
|
|||||||
function ADChainRun.apply(adEnv, data, result)
|
function ADChainRun.apply(adEnv, data, result)
|
||||||
local okFields, errFields = pcall(ADChainRun.switchFields, data, result.actions)
|
local okFields, errFields = pcall(ADChainRun.switchFields, data, result.actions)
|
||||||
if not okFields then warn("markskift fejlede: %s", tostring(errFields)) end
|
if not okFields then warn("markskift fejlede: %s", tostring(errFields)) end
|
||||||
local okProd, errProd = pcall(ADChainRun.toggleProductions, data, result.prod, result.chain.needRecipes)
|
local okProd, errProd = pcall(ADChainRun.toggleProductions, data, result.prod)
|
||||||
if not okProd then warn("mellemled fejlede: %s", tostring(errProd)) end
|
if not okProd then warn("mellemled fejlede: %s", tostring(errProd)) end
|
||||||
local okNew, created = pcall(ADChainRun.createFlows, adEnv, data, result.edges)
|
local okNew, created = pcall(ADChainRun.createFlows, adEnv, data, result.edges)
|
||||||
if not okNew then warn("nye flows fejlede: %s", tostring(created)) end
|
if not okNew then warn("nye flows fejlede: %s", tostring(created)) end
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ local function rootRows(rows, root, last, ctx, isExpanded)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Pausede rødder: recipesWithPaused slukker dem, så modellen ser dem ikke som rødder -> grå linje med [Genoptag].
|
-- Pausede rødder: modelRecipes markerer dem paused, så modellen ser dem ikke som rødder -> grå linje med [Genoptag].
|
||||||
local function pausedRows(rows, last, ctx)
|
local function pausedRows(rows, last, ctx)
|
||||||
local present, keys = {}, {}
|
local present, keys = {}, {}
|
||||||
for _, root in ipairs(last.chain ~= nil and last.chain.roots or {}) do present[root.key] = true end
|
for _, root in ipairs(last.chain ~= nil and last.chain.roots or {}) do present[root.key] = true end
|
||||||
|
|||||||
Reference in New Issue
Block a user