-- manager/config.lua — Configuration constants, data tables, and lookup structures -- Usage: local cfg = dofile("manager/config.lua")(log) return function(log) 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 = ".inventory_cache" C.SMELTER_MONITOR_SIDE = "top" C.DISABLED_RECIPES_FILE = ".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 -- 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 = ".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.logLevel then log.setLevel(cfg.logLevel) end log.info("CONFIG", "Loaded from %s", CONFIG_FILE) end ------------------------------------------------- -- Data tables ------------------------------------------------- C.SMELTABLE = dofile("data/smeltable.lua") C.FUEL_LIST = dofile("data/fuel.lua") local _compostData = dofile("data/compostable.lua") C.COMPOSTABLE = _compostData.items C.COMPOST_TRASH = _compostData.trash C.CRAFTABLE = dofile("data/craftable.lua") C.LOW_STOCK_ALERTS = dofile("data/alerts.lua") -- Pre-build furnace compatibility sets for O(1) lookup for _, recipe in pairs(C.SMELTABLE) do recipe.furnaceSet = {} for _, ft in ipairs(recipe.furnaces) do recipe.furnaceSet[ft] = true end end -- Pre-built smelt candidate lists per furnace type C.smeltCandidatesByType = {} do 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 -- 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