_configPath was called at lines 26/28 (CACHE_FILE, DISABLED_RECIPES_FILE) but only defined at line 79. Moved the definition to the top of the function body so it exists before the first call.
190 lines
7.1 KiB
Lua
190 lines
7.1 KiB
Lua
-- manager/config.lua — Configuration constants, data tables, and lookup structures
|
|
-- Usage: local cfg = dofile(_path("manager/config.lua"))(log, _path)
|
|
|
|
return function(log, _path)
|
|
|
|
-- Fall back to CWD-relative if _path not provided (standalone use)
|
|
if not _path then _path = function(p) return p end end
|
|
|
|
-- Persistent config path: survives Opus package updates
|
|
local _PERSIST_DIR = "usr/config/inventory-manager"
|
|
local function _configPath(rel)
|
|
if fs.isDir(_PERSIST_DIR) or fs.isDir("packages/inventory-manager") then
|
|
if not fs.isDir(_PERSIST_DIR) then fs.makeDir(_PERSIST_DIR) end
|
|
return fs.combine(_PERSIST_DIR, rel)
|
|
end
|
|
return _path(rel)
|
|
end
|
|
|
|
local C = {}
|
|
|
|
-------------------------------------------------
|
|
-- Default configuration (overridden by .manager_config)
|
|
-------------------------------------------------
|
|
|
|
C.DROPPER_NAME = "minecraft:dropper_9"
|
|
C.BARREL_NAME = "minecraft:barrel_0"
|
|
C.POLL_INTERVAL = 2
|
|
C.MONITOR_SIDE = "left"
|
|
C.SCAN_INTERVAL = 120
|
|
C.SMELT_INTERVAL = 3
|
|
C.SMELT_RESERVE = 128
|
|
C.DEFRAG_INTERVAL = 600
|
|
C.COMPOST_INTERVAL = 3
|
|
C.ALERT_INTERVAL = 15
|
|
C.CACHE_FILE = _configPath(".inventory_cache")
|
|
C.SMELTER_MONITOR_SIDE = "top"
|
|
C.DISABLED_RECIPES_FILE = _configPath(".disabled_recipes")
|
|
|
|
-- Network
|
|
C.BROADCAST_CHANNEL = 4200
|
|
C.ORDER_CHANNEL = 4201
|
|
C.BROADCAST_INTERVAL = 1
|
|
C.CRAFT_CHANNEL = 4203
|
|
C.CRAFT_REPLY_CHANNEL = 4204
|
|
C.SYSTEM_CHANNEL = 4205
|
|
|
|
-- Crafting
|
|
C.CRAFT_TIMEOUT = 15
|
|
C.GRID_TO_SLOT = {1, 2, 3, 5, 6, 7, 9, 10, 11}
|
|
|
|
-- Compost (overridable via config file)
|
|
C.COMPOST_RESERVE = 128
|
|
C.COMPOST_DROPPER = "minecraft:dropper_10"
|
|
C.COMPOST_HOPPER = "minecraft:hopper_0"
|
|
|
|
-- Peripheral
|
|
C.PERIPHERAL_CACHE_TTL = 5
|
|
|
|
-- Parallel scanning
|
|
C.PARALLEL_SCAN_CHUNKS = 8
|
|
|
|
-- Storage priority (higher = preferred; keyed by chest peripheral name)
|
|
C.CHEST_PRIORITY = {}
|
|
|
|
-- Builder / supply manifest
|
|
C.SUPPLY_CHEST = "" -- peripheral name of supply chest (empty = disabled)
|
|
C.SUPPLY_INTERVAL = 10 -- seconds between supply checks
|
|
C.SUPPLY_MANIFEST = {} -- { { name = "mod:item", count = N }, ... }
|
|
|
|
-- Furnace types
|
|
C.FURNACE_TYPES = {
|
|
"minecraft:furnace",
|
|
"minecraft:smoker",
|
|
"minecraft:blast_furnace",
|
|
}
|
|
C.SLOT_INPUT = 1
|
|
C.SLOT_FUEL = 2
|
|
C.SLOT_OUTPUT = 3
|
|
|
|
-------------------------------------------------
|
|
-- Config file loader
|
|
-------------------------------------------------
|
|
|
|
local CONFIG_FILE = _configPath(".manager_config")
|
|
|
|
function C.loadConfig()
|
|
if not fs.exists(CONFIG_FILE) then return end
|
|
local f = fs.open(CONFIG_FILE, "r")
|
|
local data = f.readAll()
|
|
f.close()
|
|
local ok, cfg = pcall(textutils.unserialiseJSON, data)
|
|
if not ok or not cfg then
|
|
log.warn("CONFIG", "Failed to parse %s", CONFIG_FILE)
|
|
return
|
|
end
|
|
C._raw = cfg
|
|
if cfg.dropperName then C.DROPPER_NAME = cfg.dropperName end
|
|
if cfg.barrelName then C.BARREL_NAME = cfg.barrelName end
|
|
if cfg.monitorSide then C.MONITOR_SIDE = cfg.monitorSide end
|
|
if cfg.smelterMonitorSide then C.SMELTER_MONITOR_SIDE = cfg.smelterMonitorSide end
|
|
if cfg.pollInterval then C.POLL_INTERVAL = cfg.pollInterval end
|
|
if cfg.scanInterval then C.SCAN_INTERVAL = cfg.scanInterval end
|
|
if cfg.smeltInterval then C.SMELT_INTERVAL = cfg.smeltInterval end
|
|
if cfg.defragInterval then C.DEFRAG_INTERVAL = cfg.defragInterval end
|
|
if cfg.compostInterval then C.COMPOST_INTERVAL = cfg.compostInterval end
|
|
if cfg.alertInterval then C.ALERT_INTERVAL = cfg.alertInterval end
|
|
if cfg.broadcastInterval then C.BROADCAST_INTERVAL = cfg.broadcastInterval end
|
|
if cfg.smeltReserve then C.SMELT_RESERVE = cfg.smeltReserve end
|
|
if cfg.broadcastChannel then C.BROADCAST_CHANNEL = cfg.broadcastChannel end
|
|
if cfg.orderChannel then C.ORDER_CHANNEL = cfg.orderChannel end
|
|
if cfg.craftChannel then C.CRAFT_CHANNEL = cfg.craftChannel end
|
|
if cfg.craftReplyChannel then C.CRAFT_REPLY_CHANNEL = cfg.craftReplyChannel end
|
|
if cfg.compostReserve then C.COMPOST_RESERVE = cfg.compostReserve end
|
|
if cfg.compostDropper then C.COMPOST_DROPPER = cfg.compostDropper end
|
|
if cfg.compostHopper then C.COMPOST_HOPPER = cfg.compostHopper end
|
|
if cfg.parallelScanChunks then C.PARALLEL_SCAN_CHUNKS = cfg.parallelScanChunks end
|
|
if cfg.chestPriority then C.CHEST_PRIORITY = cfg.chestPriority end
|
|
if cfg.supplyChest then C.SUPPLY_CHEST = cfg.supplyChest end
|
|
if cfg.supplyInterval then C.SUPPLY_INTERVAL = cfg.supplyInterval end
|
|
if cfg.supplyManifest then C.SUPPLY_MANIFEST = cfg.supplyManifest end
|
|
if cfg.logLevel then log.setLevel(cfg.logLevel) end
|
|
log.info("CONFIG", "Loaded from %s", CONFIG_FILE)
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- Data tables
|
|
-------------------------------------------------
|
|
|
|
C.FUEL_LIST = dofile(_path("data/fuel.lua"))
|
|
local _compostData = dofile(_path("data/compostable.lua"))
|
|
C.COMPOSTABLE = _compostData.items
|
|
C.COMPOST_TRASH = _compostData.trash
|
|
C.LOW_STOCK_ALERTS = dofile(_path("data/alerts.lua"))
|
|
|
|
-- Recipe book: merges built-in recipes + user-learned recipes
|
|
local recipeBook = dofile(_path("lib/recipeBook.lua"))
|
|
recipeBook.init(_configPath(".recipes.db"))
|
|
recipeBook.loadLegacyCrafting(dofile(_path("data/craftable.lua")))
|
|
recipeBook.loadLegacySmelting(dofile(_path("data/smeltable.lua")))
|
|
C.recipeBook = recipeBook
|
|
C.SMELTABLE = recipeBook.getSmeltingTable()
|
|
C.CRAFTABLE = recipeBook.getCraftingList()
|
|
|
|
-- Rebuild furnace/smelt indices from current recipe data
|
|
function C.rebuildIndices()
|
|
for _, recipe in pairs(C.SMELTABLE) do
|
|
recipe.furnaceSet = {}
|
|
for _, ft in ipairs(recipe.furnaces) do
|
|
recipe.furnaceSet[ft] = true
|
|
end
|
|
end
|
|
C.smeltCandidatesByType = {}
|
|
for _, ftype in ipairs(C.FURNACE_TYPES) do
|
|
C.smeltCandidatesByType[ftype] = {}
|
|
end
|
|
for itemName, recipe in pairs(C.SMELTABLE) do
|
|
local isFood = recipe.furnaceSet["minecraft:smoker"] or false
|
|
for ft in pairs(recipe.furnaceSet) do
|
|
table.insert(C.smeltCandidatesByType[ft], { name = itemName, recipe = recipe, food = isFood })
|
|
end
|
|
end
|
|
for _, list in pairs(C.smeltCandidatesByType) do
|
|
table.sort(list, function(a, b)
|
|
if a.food ~= b.food then return a.food end
|
|
return a.name < b.name
|
|
end)
|
|
end
|
|
end
|
|
|
|
-- Refresh recipes from recipeBook and rebuild all indices
|
|
function C.refreshRecipes()
|
|
C.SMELTABLE = C.recipeBook.getSmeltingTable()
|
|
C.CRAFTABLE = C.recipeBook.getCraftingList()
|
|
C.rebuildIndices()
|
|
end
|
|
|
|
C.rebuildIndices()
|
|
|
|
-- Build fuel set for quick lookup
|
|
C.FUEL_SET = {}
|
|
for _, f in ipairs(C.FUEL_LIST) do C.FUEL_SET[f.name] = true end
|
|
|
|
-- Build compostable set for quick lookup
|
|
C.COMPOSTABLE_SET = {}
|
|
for _, name in ipairs(C.COMPOSTABLE) do C.COMPOSTABLE_SET[name] = true end
|
|
|
|
return C
|
|
|
|
end
|