From 45bbc72fc351c6ca6e4cc5117dbdaa79291f64e0 Mon Sep 17 00:00:00 2001 From: kepler155c Date: Wed, 3 Jan 2018 02:41:56 -0500 Subject: [PATCH] autocrafting improvements --- apis/chestAdapter18.lua | 25 +-- apis/controllerAdapter.lua | 18 +++ apis/inventoryAdapter.lua | 4 +- apis/itemDB.lua | 4 - apis/refinedAdapter.lua | 14 +- apis/turtle/craft.lua | 153 ++++++++---------- apis/turtle/crafting.lua | 9 +- apps/chestManager.lua | 160 +++++++------------ apps/crafter.lua | 239 +++++++++++++---------------- apps/levelEmitter.lua | 4 +- apps/treefarm.lua | 8 +- etc/recipes/appliedenergistics2.db | 7 - etc/recipes/exnihilo.db | 1 + 13 files changed, 289 insertions(+), 357 deletions(-) create mode 100644 apis/controllerAdapter.lua diff --git a/apis/chestAdapter18.lua b/apis/chestAdapter18.lua index 24406af..6bda5e3 100644 --- a/apis/chestAdapter18.lua +++ b/apis/chestAdapter18.lua @@ -24,15 +24,14 @@ function ChestAdapter:init(args) Util.merge(self, args) local chest - if not self.autoDetect then + if self.autoDetect then + chest = Peripheral.getByMethod('list') + else chest = Peripheral.getBySide(self.wrapSide) if chest and not chest.list then chest = nil end end - if not chest then - chest = Peripheral.getByMethod('list') - end if chest then Util.merge(self, chest) @@ -55,17 +54,11 @@ function ChestAdapter:getCachedItemDetails(item, k) if not detail then local s, m = pcall(function() detail = self.getItemMeta(k) end) if not detail then -debug(item) -debug(m) -debug('no details') -- error('Inventory has changed') return end -- NOT SUFFICIENT if detail.name ~= item.name then -debug('name change ?') -debug(item) -debug(detail) -- error('Inventory has changed') return end @@ -76,7 +69,6 @@ debug(detail) end end -debug('adding') itemDB:add(detail) end if detail then @@ -92,7 +84,6 @@ end function ChestAdapter:listItems(throttle) local cache = { } local items = { } -debug('listing') throttle = throttle or Util.throttle() for k,v in pairs(self.list()) do @@ -103,8 +94,6 @@ debug('listing') if not entry then entry = self:getCachedItemDetails(v, k) if not entry then - debug(key) - debug('inv changed') return -- Inventory has changed end entry.count = 0 @@ -118,15 +107,12 @@ debug('listing') throttle() end end ---read() itemDB:flush() -debug('done listing') if not Util.empty(items) then self.cache = cache return items end -debug('its empty') end function ChestAdapter:getItemInfo(item) @@ -177,11 +163,14 @@ end function ChestAdapter:eject(item, qty, direction) local s, m = pcall(function() local stacks = self.list() + local maxStack = itemDB:getMaxCount(item) for key,stack in Util.rpairs(stacks) do if stack.name == item.name and (not item.damage or stack.damage == item.damage) and (not item.nbtHash or stack.nbtHash == item.nbtHash) then - local amount = math.min(qty, stack.count) + local amount = math.min(maxStack, math.min(qty, stack.count)) +debug({ key, amount }) +debug(stack) if amount > 0 then self.drop(key, amount, direction) end diff --git a/apis/controllerAdapter.lua b/apis/controllerAdapter.lua new file mode 100644 index 0000000..39d7683 --- /dev/null +++ b/apis/controllerAdapter.lua @@ -0,0 +1,18 @@ +local Adapter = { } + +function Adapter.wrap(args) + local adapters = { + 'refinedAdapter', + 'meAdapter', + } + + for _,adapterType in ipairs(adapters) do + local adapter = require(adapterType)(args) + + if adapter:isValid() then + return adapter + end + end +end + +return Adapter diff --git a/apis/inventoryAdapter.lua b/apis/inventoryAdapter.lua index cb34eb9..4e29686 100644 --- a/apis/inventoryAdapter.lua +++ b/apis/inventoryAdapter.lua @@ -2,8 +2,8 @@ local Adapter = { } function Adapter.wrap(args) local adapters = { - 'refinedAdapter', - 'meAdapter', + --'refinedAdapter', + --'meAdapter', 'chestAdapter18', 'chestAdapter', } diff --git a/apis/itemDB.lua b/apis/itemDB.lua index e01c2fa..a95ded2 100644 --- a/apis/itemDB.lua +++ b/apis/itemDB.lua @@ -141,10 +141,6 @@ function itemDB:getName(item) end function itemDB:getMaxCount(item) - if type(item) == 'string' then - item = self:splitKey(item) - end - local detail = self:get(item) if detail then return detail.maxCount diff --git a/apis/refinedAdapter.lua b/apis/refinedAdapter.lua index d7e762b..1611f3f 100644 --- a/apis/refinedAdapter.lua +++ b/apis/refinedAdapter.lua @@ -18,12 +18,22 @@ function RefinedAdapter:init(args) local defaults = { items = { }, name = 'refinedStorage', + direction = 'up', + wrapSide = 'bottom', } Util.merge(self, defaults) Util.merge(self, args) - local controller = Peripheral.getByType('refinedstorage:controller') or - Peripheral.getByMethod('listAvailableItems') + local controller + if self.autoDetect then + controller = Peripheral.getByType('refinedstorage:controller') + else + controller = Peripheral.getBySide(self.wrapSide) + if controller and not controller.listAvailableItems then + controller = nil + end + end + if controller then Util.merge(self, controller) end diff --git a/apis/turtle/craft.lua b/apis/turtle/craft.lua index c5bdf38..96d3c61 100644 --- a/apis/turtle/craft.lua +++ b/apis/turtle/craft.lua @@ -1,3 +1,4 @@ +local itemDB = require('itemDB') local Util = require('util') local fs = _G.fs @@ -32,8 +33,11 @@ local function splitKey(key) return item end -function Craft.getItemCount(items, key) - local item = splitKey(key) +function Craft.getItemCount(items, item) + if type(item) == 'string' then + item = splitKey(item) + end + local count = 0 for _,v in pairs(items) do if v.name == item.name and @@ -124,6 +128,7 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter) local iqty = icount * count - itemCount local crafted = Craft.craftRecipe(irecipe, iqty, inventoryAdapter) if crafted ~= iqty then + turtle.select(1) return 0 end @@ -145,102 +150,80 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter) return crafted * recipe.count end +local function makeRecipeKey(item) + if type(item) == 'string' then + item = splitKey(item) + end + return table.concat({ item.name, item.damage or 0, item.nbtHash }, ':') +end + +function Craft.findRecipe(item) + return Craft.recipes[makeRecipeKey(item)] +end + -- determine the full list of ingredients needed to craft -- a quantity of a recipe. --- negative quantities denote missing ingredients -function Craft.getResourceList(inRecipe, items, inCount) +function Craft.getResourceList(recipe, items, inCount) local summed = { } - local throttle = Util.throttle() - local function sumItems(recipe, count) - for key,iqty in pairs(Craft.sumIngredients(recipe)) do - throttle() - local item = splitKey(key) - local summedItem = summed[key] - if not summedItem then - summedItem = Util.shallowCopy(item) - summedItem.recipe = Craft.recipes[key] - summedItem.count = Craft.getItemCount(items, key) - summed[key] = summedItem + local function sumItems(key, count) + local item = itemDB:splitKey(key) + local summedItem = summed[key] + if not summedItem then + summedItem = Util.shallowCopy(item) + summedItem.recipe = Craft.findRecipe(key) + summedItem.count = Craft.getItemCount(items, item) + summedItem.displayName = itemDB:getName(item) + summedItem.total = 0 + summedItem.need = 0 + summedItem.used = 0 + summed[key] = summedItem + end + local total = count + local used = math.min(summedItem.count, total) + local need = total - used + + if summedItem.recipe and summedItem.recipe.craftingTools and summedItem.recipe.craftingTools[key] then + summedItem.total = 1 + if summedItem.count > 0 then + summedItem.used = 1 + summedItem.need = 0 + need = 0 + else + if not summedItem.recipe then + summedItem.need = 1 + need = 1 + end end - summedItem.count = summedItem.count - (count * iqty) - if summedItem.recipe and summedItem.count < 0 then - local need = math.ceil(-summedItem.count / summedItem.recipe.count) - summedItem.count = 0 - sumItems(summedItem.recipe, need) + else + summedItem.total = summedItem.total + total + summedItem.count = summedItem.count - used + summedItem.used = summedItem.used + used + if not summedItem.recipe then + summedItem.need = summedItem.need + need + end + end + + if need > 0 and summedItem.recipe then + need = math.ceil(need / summedItem.recipe.count) + for ikey,iqty in pairs(Craft.sumIngredients(summedItem.recipe)) do + sumItems(ikey, math.ceil(need * iqty)) end end end - sumItems(inRecipe, math.ceil(inCount / inRecipe.count)) + inCount = math.ceil(inCount / recipe.count) + for ikey,iqty in pairs(Craft.sumIngredients(recipe)) do + sumItems(ikey, math.ceil(inCount * iqty)) + end return summed end -function Craft.getResourceList3(inRecipe, items, inCount, inventoryAdapter) - local summed = { } - local throttle = Util.throttle() - - local function sumItems(recipe, count) - count = math.ceil(count / recipe.count) - local craftable = count - - for key,iqty in pairs(Craft.sumIngredients(recipe)) do - throttle() - local item = splitKey(key) - local summedItem = summed[key] - if not summedItem then - summedItem = Util.shallowCopy(item) - summedItem.recipe = Craft.recipes[key] - summedItem.count = Craft.getItemCount(items, key) - summedItem.total = 0 - summedItem.need = 0 - summedItem.used = 0 - summedItem.craftable = 0 - summed[key] = summedItem - end -debug(key) - local total = count * iqty -- 4 * 2 - local used = math.min(summedItem.count, total) -- 5 - local need = total - used -- 3 - - if recipe.craftingTools and recipe.craftingTools[key] then - summedItem.total = 1 - if summedItem.count > 0 then - summedItem.used = 1 - need = 0 - else - need = 1 - end - else - summedItem.total = summedItem.total + total - summedItem.count = summedItem.count - used - summedItem.used = summedItem.used + used - end - - if need > 0 then - if not summedItem.recipe then - craftable = math.min(craftable, math.floor(used / iqty)) - summedItem.need = summedItem.need + need - else - local c = sumItems(summedItem.recipe, need) -- 4 - craftable = math.min(craftable, math.floor((used + c) / iqty)) - summedItem.craftable = summedItem.craftable + c - end - end - end - - --[[ - if inventoryAdapter and craftable > 0 then - craftable = Craft.craftRecipe(recipe, craftable, inventoryAdapter) - clearGrid(inventoryAdapter) - end - ]] - - return craftable * recipe.count - end - - return sumItems(inRecipe, inCount), summed +function Craft.getResourceList4(inRecipe, items, count) + local summed = Craft.getResourceList(inRecipe, items, count) +-- filter down to just raw materials + return Util.filter(summed, function(a) return a.used > 0 or a.need > 0 end) end -- given a certain quantity, return how many of those can be crafted diff --git a/apis/turtle/crafting.lua b/apis/turtle/crafting.lua index e285eb8..9311317 100644 --- a/apis/turtle/crafting.lua +++ b/apis/turtle/crafting.lua @@ -6,11 +6,13 @@ local turtle = _G.turtle local CRAFTING_TABLE = 'minecraft:crafting_table' local function clearGrid(inventory) +print('clearing') for i = 1, 16 do local count = turtle.getItemCount(i) if count > 0 then inventory:insert(i, count) if turtle.getItemCount(i) ~= 0 then +print('failed to insert') return false end end @@ -19,7 +21,7 @@ local function clearGrid(inventory) end function turtle.craftItem(item, count, inventoryInfo) - local success + local success, msg local inventory = Adapter.wrap(inventoryInfo) if not inventory then @@ -46,7 +48,8 @@ function turtle.craftItem(item, count, inventoryInfo) equipped = turtle.getItemDetail(slot.index) end - success = Craft.craftRecipe(item, count or 1, inventory) + clearGrid(inventory) + success, msg = Craft.craftRecipe(item, count or 1, inventory) if equipped then turtle.selectOpenSlot() @@ -54,7 +57,7 @@ function turtle.craftItem(item, count, inventoryInfo) turtle.equip(side, equipped.name .. ':' .. equipped.damage) end - return success + return success, msg end function turtle.canCraft(item, count, items) diff --git a/apps/chestManager.lua b/apps/chestManager.lua index 0475fd3..9b083a0 100644 --- a/apps/chestManager.lua +++ b/apps/chestManager.lua @@ -1,18 +1,18 @@ _G.requireInjector() local Ansi = require('ansi') -local ChestAdapter = require('chestAdapter18') local Config = require('config') local Craft = require('turtle.craft') local Event = require('event') local itemDB = require('itemDB') -local MEAdapater = require('meAdapter') local Peripheral = require('peripheral') -local RefinedAdapter = require('refinedAdapter') local Terminal = require('terminal') local UI = require('ui') local Util = require('util') +local ControllerAdapter = require('controllerAdapter') +local InventoryAdapter = require('inventoryAdapter') + local device = _G.device local multishell = _ENV.multishell local peripheral = _G.peripheral @@ -22,35 +22,23 @@ local turtle = _G.turtle multishell.setTitle(multishell.getCurrent(), 'Resource Manager') --- 3 wide monitor (any side of turtle) - -- Config location is /sys/config/chestManager -- adjust directions in that file if needed - local config = { - trashDirection = 'up', -- trash /chest in relation to chest - inventoryDirection = { direction = 'north', wrapSide = 'back' }, - chestDirection = { direction = 'down', wrapSide = 'top' }, + trashDirection = 'up', -- trash /chest in relation to chest + inventoryDirection = { direction = 'north', wrapSide = 'back' }, + chestDirection = { direction = 'down', wrapSide = 'top' }, + controllerDirection = { direction = 'south', wrapSide = 'right' }, } Config.load('chestManager', config) -local inventoryAdapter = ChestAdapter(config.inventoryDirection) -local turtleChestAdapter = ChestAdapter(config.chestDirection) +local inventoryAdapter = InventoryAdapter.wrap(config.inventoryDirection) +local turtleChestAdapter = InventoryAdapter.wrap(config.chestDirection) +local controllerAdapter = ControllerAdapter.wrap(config.controllerDirection) local duckAntenna -local controller = RefinedAdapter() -if not controller:isValid() then - controller = MEAdapater(config.inventoryDirection) - if not controller:isValid() then - controller = nil - else - inventoryAdapter = controller -- ME functions as inventory and crafting - end -end - if device.workbench then - local oppositeSide = { [ 'left' ] = 'right', [ 'right' ] = 'left', @@ -83,21 +71,6 @@ local function getItem(items, inItem, ignoreDamage, ignoreNbtHash) end end -local function getItemQuantity(items, item) - local count = 0 - for _,v in pairs(items) do - if v.name == item.name and - (not item.damage or v.damage == item.damage) and - v.nbtHash == item.nbtHash then - if item.damage then - return v.count - end - count = count + v.count - end - end - return count -end - local function uniqueKey(item) return table.concat({ item.name, item.damage, item.nbtHash }, ':') end @@ -145,6 +118,7 @@ local function listItems() if not items then -- error('could not check inventory') term.clear() +print('Communication failure') print('rebooting in 5 secs') os.sleep(5) os.reboot() @@ -190,7 +164,6 @@ local function clearGrid() if count > 0 then inventoryAdapter:insert(i, count) if turtle.getItemCount(i) ~= 0 then - debug('insert failed') return false end end @@ -229,28 +202,6 @@ local function craftItem(recipe, items, originalItem, craftList, count) if missing.name then originalItem.status = string.format('%s missing', itemDB:getName(missing.name)) originalItem.statusCode = 'missing' --- debug(missing.name) - end - - if originalItem.forceCrafting and toCraft == 0 then - for key,qty in pairs(Craft.sumIngredients(recipe)) do - local iRecipe = Craft.recipes[key] - if iRecipe then - local need = count * qty - local has = getItemQuantity(items, itemDB:splitKey(key)) ---debug({ key, need, has }) - if has < need then ---debug('crafting ' .. key .. ' - ' .. need - has) ---read() - craftItem(iRecipe, items, originalItem, { }, math.ceil((need - has) / iRecipe.count)) - items = listItems() - if not items then - error('list failed') - --return 0 - end - end - end - end end local crafted = 0 @@ -263,11 +214,11 @@ local function craftItem(recipe, items, originalItem, craftList, count) end if count > 0 and items then - local ingredients = Craft.getResourceList(recipe, items, count) + local ingredients = Craft.getResourceList4(recipe, items, count) for _,ingredient in pairs(ingredients) do --if not ingredient.recipe and ingredient.count < 0 then - if ingredient.count < 0 then - addCraftingRequest(ingredient, craftList, -ingredient.count) + if ingredient.need > 0 then + addCraftingRequest(ingredient, craftList, ingredient.need) end end end @@ -288,7 +239,7 @@ local function forceCraftItem(inRecipe, items, originalItem, craftList, inCount) local summedItem = summed[key] if not summedItem then summedItem = Util.shallowCopy(item) - summedItem.recipe = Craft.recipes[key] + summedItem.recipe = Craft.findRecipe(item) summedItem.count = Craft.getItemCount(items, key) summedItem.need = 0 summedItem.used = 0 @@ -321,17 +272,18 @@ local function forceCraftItem(inRecipe, items, originalItem, craftList, inCount) local c = sumItems(summedItem.recipe, need) -- 4 craftable = math.min(craftable, math.floor((used + c) / iqty)) summedItem.craftable = summedItem.craftable + c + end end end - if craftable > 0 then - craftable = Craft.craftRecipe(recipe, craftable, inventoryAdapter) / recipe.count + craftable = Craft.craftRecipe(recipe, craftable * recipe.count, inventoryAdapter) / recipe.count clearGrid() end return craftable * recipe.count end + local count = sumItems(inRecipe, inCount) -- local count, summed = Craft.getResourceList3(inRecipe, items, inCount, inventoryAdapter) @@ -348,7 +300,6 @@ local function forceCraftItem(inRecipe, items, originalItem, craftList, inCount) end local function craftItems(craftList, allItems) - for _,key in pairs(Util.keys(craftList)) do local item = craftList[key] local recipe = Craft.recipes[key] @@ -371,17 +322,17 @@ local function craftItems(craftList, allItems) for key,item in pairs(craftList) do if not Craft.recipes[key] and not item.rsControl then - if not controller then + if not controllerAdapter then item.status = '(no recipe)' else - if controller:isCrafting(item) then + if controllerAdapter:isCrafting(item) then item.status = '(crafting)' else local count = item.count while count >= 1 do -- try to request smaller quantities until successful local s = pcall(function() item.status = '(no recipe)' - if not controller:craft(item, count) then + if not controllerAdapter:craft(item, count) then item.status = '(missing ingredients)' error('failed') end @@ -442,6 +393,8 @@ local function jobMonitor() return colors.red elseif row.statusCode == 'missing' then return colors.yellow + elseif row.statusCode == 'success' then + return colors.lime end return UI.Grid:getRowTextColor(row, selected) end @@ -514,11 +467,6 @@ local function watchResources(items) item.damage = 0 end local key = uniqueKey(res) -if res.name == 'harvestcraft:applesauceitem' then - _G._p = items - debug('applesause') - error('applesauce') -end craftList[key] = { damage = item.damage, @@ -801,7 +749,6 @@ function itemPage:eventHandler(event) else filtered.ignoreNbtHash = nil end -debug(filtered) resources[originalKey] = nil resources[uniqueKey(filtered)] = filtered saveResources() @@ -834,15 +781,13 @@ local listingPage = UI.Page { sortColumn = 'displayName', }, statusBar = UI.StatusBar { - filterText = UI.Text { - x = 2, - value = 'Filter', - }, filter = UI.TextEntry { - x = 9, ex = -5, + x = 1, ex = -4, limit = 50, - backgroundColor = colors.gray, - backgroundFocusColor = colors.gray, + shadowText = 'filter', + shadowTextColor = colors.gray, + backgroundColor = colors.cyan, + backgroundFocusColor = colors.cyan, }, display = UI.Button { x = -3, @@ -858,6 +803,10 @@ local listingPage = UI.Page { displayMode = 0, } +function listingPage.statusBar:draw() + return UI.Window.draw(self) +end + function listingPage.grid:getRowTextColor(row, selected) if row.is_craftable then return colors.yellow @@ -880,10 +829,6 @@ function listingPage.grid:getDisplayValues(row) return row end -function listingPage.statusBar:draw() - return UI.Window.draw(self) -end - function listingPage:eventHandler(event) if event.type == 'quit' then UI:exitPullEvents() @@ -1062,7 +1007,7 @@ local function learnRecipe(page) for k,ingredient in pairs(ingredients) do if ingredient.maxDamage > 0 then - ingredient.damage = '*' + ingredient.damage = '*' -- I don't think this is right end ingredients[k] = uniqueKey(ingredient) end @@ -1137,9 +1082,7 @@ function learnPage:eventHandler(event) end local craftPage = UI.Page { - titleBar = UI.TitleBar { - title = "Information", - }, + titleBar = UI.TitleBar { }, wizard = UI.Wizard { y = 2, ey = -2, pages = { @@ -1170,14 +1113,13 @@ local craftPage = UI.Page { }, resources = UI.Window { index = 2, - grid = UI.Grid { + grid = UI.ScrollingGrid { y = 2, ey = -2, columns = { { heading = 'Name', key = 'displayName' }, - { heading = 'Total', key = 'total' , width = 4 }, - { heading = 'Used', key = 'used' , width = 4 }, - { heading = 'Craf', key = 'craftable' , width = 4 }, - { heading = 'Need', key = 'need' , width = 4 }, + { heading = 'Total', key = 'total' , width = 5 }, + { heading = 'Used', key = 'used' , width = 5 }, + { heading = 'Need', key = 'need' , width = 5 }, }, sortColumn = 'displayName', }, @@ -1189,6 +1131,7 @@ local craftPage = UI.Page { function craftPage:enable(item) self.item = item self:focusFirst() + self.titleBar.title = itemDB:getName(item) -- self.wizard.pages.quantity.eject.value = true UI.Page.enable(self) end @@ -1203,27 +1146,39 @@ function craftPage.wizard.pages.resources.grid:getDisplayValues(row) row = Util.shallowCopy(row) row.total = Util.toBytes(row.total) row.used = dv(row.used) - row.craftable = dv(row.craftable) row.need = dv(row.need) return row end function craftPage.wizard.pages.resources.grid:getRowTextColor(row, selected) - if row.need - row.craftable > 0 then + if row.need > 0 then return colors.orange end return UI.Grid:getRowTextColor(row, selected) end +function craftPage.wizard:eventHandler(event) + if event.type == 'nextView' then + local count = tonumber(self.pages.quantity.count.value) + if not count or count <= 0 then + self.pages.quantity.count.backgroundColor = colors.red + self.pages.quantity.count:draw() + return false + end + self.pages.quantity.count.backgroundColor = colors.black + end + return UI.Wizard.eventHandler(self, event) +end + function craftPage:eventHandler(event) if event.type == 'cancel' then UI:setPreviousPage() elseif event.type == 'enable_view' and event.view == self.wizard.pages.resources then local items = listItems() - local count = self.wizard.pages.quantity.count.value - local recipe = Craft.recipes[uniqueKey(self.item)] - local _, ingredients = Craft.getResourceList3(recipe, items, count) + local count = tonumber(self.wizard.pages.quantity.count.value) + local recipe = Craft.findRecipe(self.item) + local ingredients = Craft.getResourceList4(recipe, items, count) for _,v in pairs(ingredients) do v.displayName = itemDB:getName(v) end @@ -1290,9 +1245,10 @@ Event.onInterval(5, function() for _,key in pairs(Util.keys(demandCrafting)) do local item = demandCrafting[key] if item.crafted then - item.count = item.count - item.crafted + item.count = math.max(0, item.count - item.crafted) if item.count <= 0 then demandCrafting[key] = nil + item.statusCode = 'success' if item.eject then inventoryAdapter:eject(item, item.ocount, inventoryAdapter.getMetadata().state.facing) end diff --git a/apps/crafter.lua b/apps/crafter.lua index 3e37e63..4fe2cb8 100644 --- a/apps/crafter.lua +++ b/apps/crafter.lua @@ -183,64 +183,77 @@ local function getItems() return items end -local function craftItem(recipe, recipeKey, items, cItem, count) +local function craftItem(ikey, item, items) dock() - local resource = resources[recipeKey] + local resource = resources[ikey] if not resource or not resource.machine then - cItem.status = 'machine not selected' + item.status = 'machine not selected' return end local machine = Util.find(machines, 'order', resource.machine) if not machine then - cItem.status = 'invalid machine' - return - end - - if count == 0 then - for key in pairs(recipe.ingredients) do - local item = getItemWithQty(items, itemDB:splitKey(key), recipe.ignoreNbtHash) - if item.count == 0 then - cItem.status = 'Missing: ' .. (item.displayName or itemDB:getName(item)) - return false - end - end + item.status = 'invalid machine' return end local slot = 1 - for key,qty in pairs(recipe.ingredients) do - local item = getItemWithQty(items, itemDB:splitKey(key), recipe.ignoreNbtHash) - if item.count == 0 then -debug(item) - cItem.status = 'Missing: ' .. (item.displayName or itemDB:getName(item)) + local maxCount = math.ceil(item.need / item.recipe.count) + for key,qty in pairs(item.recipe.ingredients) do + local ingredient = itemDB:get(key) + local c = math.min(maxCount * qty, getItemQuantity(items, ingredient)) + c = math.min(c, ingredient.maxCount) + c = math.floor(c / qty) + if c < maxCount then + maxCount = c + end + if maxCount == 0 then + item.status = 'Missing ' .. ingredient.displayName + item.statusCode = 'missing' return end - local c = count * qty - while c > 0 do - local maxCount = math.min(c, item.maxCount) - inventoryAdapter:provide(item, maxCount, slot) - if turtle.getItemCount(slot) ~= maxCount then -- ~= maxCount then FIXXX !!! - cItem.status = 'Extract failed: ' .. (item.displayName or itemDB:getName(item)) - return - end - c = c - maxCount - slot = slot + 1 - end end + + for key,qty in pairs(item.recipe.ingredients) do + local ingredient = itemDB:get(key) +-- local c = item.craftable * qty +-- while c > 0 do + inventoryAdapter:provide(ingredient, maxCount * qty, slot) + if turtle.getItemCount(slot) ~= maxCount * qty then -- ~= maxCount then FIXXX !!! + item.status = 'Extract failed: ' .. (ingredient.displayName or itemDB:getName(ingredient)) +debug({ key, maxCount }) + return + end +-- c = c - maxCount + slot = slot + 1 + --end + end + if not gotoMachine(machine) then - cItem.status = 'failed to find machine' + item.status = 'failed to find machine' else if machine.empty then local s, l = pcall(Peripheral.call, turtle.getAction(machine.dir).side, 'list') + if not s and not l then + l = 'Unable to check empty status' + elseif not s then + s, l = pcall(Peripheral.call, + turtle.getAction(machine.dir).side, 'getProgress') + if s and l == 0 then + l = { } + elseif s then + l = { true } + end + end +debug { s, l } if not s then - cItem.status = l + item.status = l return elseif not Util.empty(l) then - cItem.status = 'machine busy' + item.status = 'machine busy' return end end @@ -251,78 +264,52 @@ debug(item) turtle.emptyInventory(turtle.dropDown) end if #turtle.getFilledSlots() ~= 0 then - cItem.status = 'machine busy' + item.status = 'machine busy' else - cItem.status = 'crafting' + item.status = 'crafting' end end end local function expandList(list, items) + local summed = { } - local function getCraftable(recipe, count) - local maxSlots = math.floor(16 / Util.size(recipe.ingredients)) + local function sumItems(key, count) + local item = itemDB:splitKey(key) + local summedItem = summed[key] + if not summedItem then + summedItem = Util.shallowCopy(item) + summedItem.recipe = recipes[key] + summedItem.count = getItemQuantity(items, item) + summedItem.displayName = itemDB:getName(item) + summedItem.total = 0 + summedItem.need = 0 + summedItem.used = 0 + summedItem.craftable = 0 + summed[key] = summedItem + end + local total = count + local used = math.min(summedItem.count, total) + local need = total - used - for key,qty in pairs(recipe.ingredients) do + summedItem.total = summedItem.total + total + summedItem.count = summedItem.count - used + summedItem.used = summedItem.used + used + summedItem.need = summedItem.need + need - local item = getItemWithQty(items, itemDB:splitKey(key), recipe.ignoreNbtHash) - - local need = qty * count - local irecipe = recipes[key] - - if item.count < need and irecipe then - need = math.ceil((need - item.count) / irecipe.count) - if not list[key] then - list[key] = Util.shallowCopy(item) - list[key].ocount = need - list[key].count = 0 - else - if not list[key].ocount then - list[key].ocount = 0 - end - list[key].ocount = list[key].ocount + need - end - - local icount = getCraftable(irecipe, need) - list[key].count = list[key].count + icount + if need > 0 and summedItem.recipe then + need = math.ceil(need / summedItem.recipe.count) + for ikey,iqty in pairs(summedItem.recipe.ingredients) do + sumItems(ikey, math.ceil(need * iqty)) end - local x = math.min(math.floor(item.count / qty), item.maxCount * maxSlots) - count = math.min(x, count) - item.count = math.max(0, item.count - (count * qty)) - end - - return count - end - - for key, item in pairs(Util.shallowCopy(list)) do - local recipe = recipes[key] - - item.count = math.ceil(item.count / recipe.count) - item.ocount = item.count - if recipe then - item.count = getCraftable(recipe, item.count) end end -end -local function craftItems(craftList) - local items = getItems() - expandList(craftList, items) - jobListGrid:update() - jobListGrid:draw() - jobListGrid:sync() - for key, item in pairs(craftList) do - local recipe = recipes[key] - if recipe then - craftItem(recipe, key, items, item, item.count) - dock() - jobListGrid:update() - jobListGrid:draw() - jobListGrid:sync() - clearGrid() - items = getItems() - end + for key, item in pairs(list) do + sumItems(key, item.count) end + + return Util.filter(summed, function(a) return a.need > 0 end) end local function watchResources(items) @@ -339,7 +326,7 @@ local function watchResources(items) item.count = getItemQuantity(items, item) if item.count < res.low then item.displayName = itemDB:getName(res) - item.count = res.low - item.count + item.count = res.low -- - item.count craftList[uniqueKey(res)] = item end end @@ -348,22 +335,31 @@ local function watchResources(items) return craftList end +local function craftItems() + local items = getItems() + local craftList = watchResources(items) + local list = expandList(craftList, items) + jobListGrid:setValues(list) + jobListGrid:update() + jobListGrid:draw() + jobListGrid:sync() + for key, item in pairs(list) do + if item.need > 0 and item.recipe then + craftItem(key, item, items) + dock() + items = getItems() -- should decrement count instead ... + jobListGrid:update() + jobListGrid:draw() + jobListGrid:sync() + clearGrid() + end + end +end + local function loadResources() resources = Util.readTable(RESOURCE_FILE) or { } for k,v in pairs(resources) do Util.merge(v, itemDB:splitKey(k)) - if v.dir then - for _,m in pairs(machines) do - if m.index == v.machine and m.dir == v.dir then - v.machine = m.order - v.dir = nil - break - end - end - if v.dir then - error('did not find') - end - end end end @@ -460,8 +456,7 @@ local function jobMonitor() parent = mon, sortColumn = 'displayName', columns = { - { heading = 'Qty', key = 'ocount', width = 6 }, - { heading = 'Qty', key = 'count', width = 6 }, + { heading = 'Qty', key = 'need', width = 6 }, { heading = 'Crafting', key = 'displayName', width = (mon.width - 18) / 2 }, { heading = 'Status', key = 'status', }, }, @@ -760,7 +755,7 @@ local machinesPage = UI.Page { previousPage = true, title = 'Machines', }, - grid = UI.Grid { + grid = UI.ScrollingGrid { y = 2, ey = -2, values = machines, columns = { @@ -873,14 +868,12 @@ local listingPage = UI.Page { }, sortColumn = 'displayName', }, - statusBar = UI.StatusBar { - filterText = UI.Text { - x = 2, - value = 'Filter', - }, + statusBar = UI.Window { + y = -1, filter = UI.TextEntry { - x = 9, ex = -2, limit = 50, + shadowText = 'filter', + shadowTextColor = colors.lightGray, backgroundColor = colors.gray, backgroundFocusColor = colors.gray, }, @@ -910,10 +903,6 @@ function listingPage.grid:getDisplayValues(row) return row end -function listingPage.statusBar:draw() - return UI.Window.draw(self) -end - function listingPage.statusBar.filter:eventHandler(event) if event.type == 'mouse_rightclick' then self.value = '' @@ -1025,18 +1014,8 @@ Event.onInterval(30, function() inventoryAdapter:provide({ name = 'minecraft:coal', damage = 1 }, 16, 1) turtle.refuel() end - local items = getItems() - if items then - local craftList = watchResources(items) - - jobListGrid:setValues(craftList) - jobListGrid:update() - jobListGrid:draw() - jobListGrid:sync() - - craftItems(craftList) - end + craftItems() end) UI:pullEvents() -jobListGrid.parent:reset() +--jobListGrid.parent:reset() diff --git a/apps/levelEmitter.lua b/apps/levelEmitter.lua index 9ba3d62..7fd4cb2 100644 --- a/apps/levelEmitter.lua +++ b/apps/levelEmitter.lua @@ -144,7 +144,7 @@ local itemPage = UI.Page { } function itemPage:enable(item) - self.item = item + self.item = Util.shallowCopy(item) self.form:setValues(item) self.titleBar.title = item.displayName or item.name @@ -179,7 +179,7 @@ function itemPage:eventHandler(event) local originalKey = uniqueKey(self.item) resources[originalKey] = nil - filtered.low = tonumber(filtered.limit) + filtered.low = tonumber(filtered.low) filtered.limit = tonumber(filtered.limit) if filtered.limit or filtered.low then resources[uniqueKey(filtered)] = filtered diff --git a/apps/treefarm.lua b/apps/treefarm.lua index 20966e6..f89ea0d 100644 --- a/apps/treefarm.lua +++ b/apps/treefarm.lua @@ -118,17 +118,21 @@ local function safePlaceBlock(item) end local function craftItem(item, qty) - local success + local success, msg if safePlaceBlock(CHEST) then Util.print('Crafting %d %s', (qty or 1), item) - success = turtle.craftItem(item, qty or 1, { + success, msg = turtle.craftItem(item, qty or 1, { wrapSide = 'top', direction = 'down', }) repeat until not turtle.suckUp() + if not success then + print(msg) + end + turtle.digUp() end diff --git a/etc/recipes/appliedenergistics2.db b/etc/recipes/appliedenergistics2.db index 7e96ab9..3c81618 100644 --- a/etc/recipes/appliedenergistics2.db +++ b/etc/recipes/appliedenergistics2.db @@ -56,13 +56,6 @@ }, count = 1, }, - [ "appliedenergistics2:crystal_seed:0:5af0f90bcc279578cf09089f43278d57" ] = { - ingredients = { - "minecraft:sand:0", - "appliedenergistics2:material:2", - }, - count = 2, - }, [ "appliedenergistics2:material:36" ] = { ingredients = { "minecraft:redstone:0", diff --git a/etc/recipes/exnihilo.db b/etc/recipes/exnihilo.db index b30c7fc..ba1b117 100644 --- a/etc/recipes/exnihilo.db +++ b/etc/recipes/exnihilo.db @@ -1,5 +1,6 @@ { [ "exnihiloadscensio:hammerStone:0" ] = { + maxCount = 1, ingredients = { [ 7 ] = "minecraft:cobblestone:0", [ 9 ] = "minecraft:stick:0",