diff --git a/apis/chestAdapter18.lua b/apis/chestAdapter18.lua index 64200dc..66b3eb5 100644 --- a/apis/chestAdapter18.lua +++ b/apis/chestAdapter18.lua @@ -7,18 +7,16 @@ local ChestAdapter = class() function ChestAdapter:init(args) local defaults = { - name = 'chest', - direction = 'down', - wrapSide = 'bottom', + name = 'chest', } Util.merge(self, defaults) Util.merge(self, args) local chest - if self.autoDetect then + if not self.side then chest = Peripheral.getByMethod('list') else - chest = Peripheral.getBySide(self.wrapSide) + chest = Peripheral.getBySide(self.side) if chest and not chest.list then chest = nil end @@ -104,7 +102,7 @@ function ChestAdapter:craftItems() end function ChestAdapter:getPercentUsed() - if self.cache then + if self.cache and self.getDrawerCount then return math.floor(Util.size(self.cache) / self.getDrawerCount() * 100) end return 0 diff --git a/apis/inventoryAdapter.lua b/apis/inventoryAdapter.lua index b2a1d59..bc41be1 100644 --- a/apis/inventoryAdapter.lua +++ b/apis/inventoryAdapter.lua @@ -2,7 +2,7 @@ local Util = require('util') local Adapter = { } -function Adapter.wrap(args, computerInfo) +function Adapter.wrap(args) local adapters = { --'refinedAdapter', --'meAdapter', @@ -10,34 +10,32 @@ function Adapter.wrap(args, computerInfo) 'chestAdapter', } - if computerInfo then + if args and args.side and args.facing and not args.direction then args = Util.shallowCopy(args) - if not args.direction and computerInfo.facing then - local horz = { top = 'down', bottom = 'up' } - args.direction = horz[args.wrapSide] + local horz = { top = 'down', bottom = 'up' } + args.direction = horz[args.side] - if not args.direction then - local sides = { - front = 0, - back = 2, - right = 1, - left = 3, - } + if not args.direction then + local sides = { + front = 0, + back = 2, + right = 1, + left = 3, + } -- pretty sure computer/turtle have sides reversed - local cards = { - east = 0, - south = 1, - west = 2, - north = 3, - } - local icards = { - [ 0 ] = 'west', - [ 1 ] = 'north', - [ 2 ] = 'east', - [ 3 ] = 'south', - } - args.direction = icards[(cards[computerInfo.facing] + sides[args.wrapSide]) % 4] - end + local cards = { + east = 0, + south = 1, + west = 2, + north = 3, + } + local icards = { + [ 0 ] = 'west', + [ 1 ] = 'north', + [ 2 ] = 'east', + [ 3 ] = 'south', + } + args.direction = icards[(cards[args.facing] + sides[args.side]) % 4] end end diff --git a/apis/itemDB.lua b/apis/itemDB.lua index 40259e2..f67a6f1 100644 --- a/apis/itemDB.lua +++ b/apis/itemDB.lua @@ -73,29 +73,15 @@ function itemDB:get(key, enforceNBT) end end - if key.nbtHash and not enforceNBT then + if key.nbtHash then item = self:get({ name = key.name, damage = key.damage }) - if item and (item.maxDamage > 0 or item.damage == key.damage) then + + if item and item.ignoreNBT then item = Util.shallowCopy(item) item.nbtHash = key.nbtHash + item.damage = key.damage return item end - - local damage = tonumber(key.damage) -debug('scan: ' .. makeKey(key)) - for _,item in pairs(self.data) do - if item.name == key.name and - ((not damage or item.maxDamage > 0) or damage == item.damage) and - item.nbtHash then - item = Util.shallowCopy(item) - item.damage = damage or item.damage - if item.maxDamage > 0 and item.damage and item.damage > 0 then - item.displayName = string.format('%s (damage: %s)', item.displayName, item.damage) - end - item.nbtHash = key.nbtHash - return item - end - end end end @@ -103,23 +89,55 @@ end If the base item contains an NBT hash, then the NBT hash uniquely identifies this item. ]]-- -function itemDB:add(item, detail) - local nItem = { name = item.name, damage = item.damage, nbtHash = item.nbtHash } - if detail.maxDamage > 0 then - nItem.damage = '*' - end +function itemDB:add(baseItem, detail) + local nItem = { + name = baseItem.name, + damage = baseItem.damage, + nbtHash = baseItem.nbtHash, + } +-- if detail.maxDamage > 0 then +-- nItem.damage = '*' +-- end +debug('--') +debug('adding ' .. makeKey(nItem)) nItem.displayName = safeString(detail.displayName) nItem.maxCount = detail.maxCount nItem.maxDamage = detail.maxDamage - TableDB.add(self, makeKey(nItem), nItem) - - if detail.maxDamage > 0 then - nItem = Util.shallowCopy(nItem) - nItem.damage = item.damage + for k,item in pairs(self.data) do + if nItem.name == item.name and + nItem.displayName == item.displayName then +debug('found: ' .. makeKey(item)) + if nItem.nbtHash ~= item.nbtHash and nItem.damage ~= item.damage then + nItem.damage = '*' + nItem.nbtHash = nil + nItem.ignoreNBT = true + self.data[k] = nil + debug('removing all ' .. makeKey(nItem)) + break + elseif nItem.damage ~= item.damage then + nItem.damage = '*' + self.data[k] = nil + debug('removing damage ' .. makeKey(nItem)) + break + elseif nItem.nbtHash ~= item.nbtHash then + nItem.nbtHash = nil + nItem.ignoreNBT = true + debug('removing nbt ' .. makeKey(nItem)) + self.data[k] = nil + break + end + end end +debug('final ' .. makeKey(nItem)) + + TableDB.add(self, makeKey(nItem), nItem) + nItem = Util.shallowCopy(nItem) + nItem.damage = baseItem.damage + nItem.nbtHash = baseItem.nbtHash + return nItem end diff --git a/apps/chestManager.lua b/apps/chestManager.lua index 41494fa..2908f98 100644 --- a/apps/chestManager.lua +++ b/apps/chestManager.lua @@ -23,24 +23,21 @@ local turtle = _G.turtle multishell.setTitle(multishell.getCurrent(), 'Resource Manager') local config = { + computerFacing = 'north', + + inventory = 'back', + craftingChest = 'top', + controller = 'none', + trashDirection = 'up', -- trash /chest in relation to chest - computer = { - facing = 'north', - desc = 'Direction computer or turtle is facing', - }, - inventory = { wrapSide = 'back', - desc = 'Location of main inventory' }, - craftingChest = { wrapSide = 'top', - desc = 'Vanilla chest used for crafting' }, - controller = { wrapSide = 'right', - desc = 'optional - AE or refined storage controller - can be same as main inventory' }, + monitor = 'type/monitor', } Config.loadWithCheck('inventoryManager', config) -local inventoryAdapter = InventoryAdapter.wrap(config.inventory, config.computer) -local turtleChestAdapter = InventoryAdapter.wrap(config.craftingChest, config.computer) -local controllerAdapter = ControllerAdapter.wrap(config.controller, config.computer) +local inventoryAdapter = InventoryAdapter.wrap({ side = config.inventory, facing = config.computerFacing }) +local turtleChestAdapter = InventoryAdapter.wrap({ side = config.craftingChest, facing = config.computerFacing }) +local controllerAdapter = ControllerAdapter.wrap({ side = config.controller, facing = config.computerFacing }) local duckAntenna if not inventoryAdapter then @@ -359,7 +356,7 @@ local function craftItems(craftList, allItems) end local function jobMonitor() - local mon = Peripheral.getByType('monitor') + local mon = Peripheral.lookup(config.monitor) if mon then mon = UI.Device({ @@ -759,6 +756,8 @@ function itemPage:eventHandler(event) end resources[originalKey] = nil resources[uniqueKey(filtered)] = filtered + + filtered.count = nil saveResources() UI:setPreviousPage() diff --git a/apps/crafter.lua b/apps/crafter.lua index 4fe2cb8..ceb6d34 100644 --- a/apps/crafter.lua +++ b/apps/crafter.lua @@ -1,6 +1,6 @@ _G.requireInjector() -local ChestAdapter = require('chestAdapter18') +local InventoryAdapter = require('inventoryAdapter') local Config = require('config') local Event = require('event') local itemDB = require('itemDB') @@ -18,16 +18,26 @@ local turtle = _G.turtle multishell.setTitle(multishell.getCurrent(), 'Crafter') local config = { - inventory = { direction = 'north', wrapSide = 'front' }, + computerFacing = 'north', + monitor = 'monitor', } Config.load('crafter', config) repeat until not turtle.forward() -local inventoryAdapter = ChestAdapter(config.inventory) -local RESOURCE_FILE = 'usr/config/resources.db' -local RECIPES_FILE = 'usr/config/recipes2.db' -local MACHINES_FILE = 'usr/config/machines.db' +local inventoryAdapter = InventoryAdapter.wrap({ side = 'front', facing = config.computerFacing }) +if not inventoryAdapter then + error('Invalid inventory configuration') +end + +local RESOURCE_FILE = 'usr/config/resources.db' +local RECIPES_FILE = 'usr/config/recipes2.db' +local MACHINES_FILE = 'usr/config/machines.db' + +local STATUS_ERROR = 'error' +local STATUS_INFO = 'info' +local STATUS_SUCCESS = 'success' +local STATUS_WARNING = 'warning' local recipes = Util.readTable(RECIPES_FILE) or { } local resources @@ -63,20 +73,6 @@ local function getItemQuantity(items, res) return count end -local function getItemWithQty(items, res, ignoreNbtHash) - for _,v in pairs(items) do - if res.name == v.name and - ((not res.damage and v.maxDamage > 0) or res.damage == v.damage) and - ((ignoreNbtHash and v.nbtHash) or res.nbtHash == v.nbtHash) then - return v - end - end - local item = Util.shallowCopy(res) - item.count = 0 - item.maxCount = 1 - return item -end - local function mergeResources(t) for _,v in pairs(resources) do local item = getItem(t, v) @@ -183,23 +179,41 @@ local function getItems() return items end -local function craftItem(ikey, item, items) +local function craftItem(ikey, item, items, machineStatus) dock() local resource = resources[ikey] if not resource or not resource.machine then - item.status = 'machine not selected' + item.statusCode = STATUS_ERROR + item.status = 'machine not defined' return end local machine = Util.find(machines, 'order', resource.machine) if not machine then + item.statusCode = STATUS_ERROR item.status = 'invalid machine' return end + local ms = machineStatus[machine.order] + if not ms then + ms = { count = 0 } + machineStatus[machine.order] = ms + end + local slot = 1 local maxCount = math.ceil(item.need / item.recipe.count) + maxCount = math.min(machine.maxCount or 64, maxCount) + + if maxCount > 0 and maxCount - ms.count <= 0 then + item.statusCode = STATUS_INFO + item.status = 'machine busy' + return + end + + maxCount = maxCount - ms.count + for key,qty in pairs(item.recipe.ingredients) do local ingredient = itemDB:get(key) local c = math.min(maxCount * qty, getItemQuantity(items, ingredient)) @@ -208,13 +222,17 @@ local function craftItem(ikey, item, items) if c < maxCount then maxCount = c end - if maxCount == 0 then + if maxCount <= 0 then item.status = 'Missing ' .. ingredient.displayName - item.statusCode = 'missing' + item.statusCode = STATUS_WARNING return end end + if machine.maxCount then + ms.count = ms.count + maxCount + end + for key,qty in pairs(item.recipe.ingredients) do local ingredient = itemDB:get(key) -- local c = item.craftable * qty @@ -222,6 +240,7 @@ local function craftItem(ikey, item, items) 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)) + item.statusCode = STATUS_ERROR debug({ key, maxCount }) return end @@ -232,6 +251,7 @@ debug({ key, maxCount }) if not gotoMachine(machine) then item.status = 'failed to find machine' + item.statusCode = STATUS_ERROR else if machine.empty then local s, l = pcall(Peripheral.call, @@ -250,9 +270,11 @@ debug({ key, maxCount }) end debug { s, l } if not s then + item.statusCode = STATUS_ERROR item.status = l return elseif not Util.empty(l) then + item.statusCode = STATUS_INFO item.status = 'machine busy' return end @@ -264,8 +286,10 @@ debug { s, l } turtle.emptyInventory(turtle.dropDown) end if #turtle.getFilledSlots() ~= 0 then + item.statusCode = STATUS_INFO item.status = 'machine busy' else + item.statusCode = STATUS_SUCCESS item.status = 'crafting' end end @@ -336,6 +360,7 @@ local function watchResources(items) end local function craftItems() + local machineStatus = { } local items = getItems() local craftList = watchResources(items) local list = expandList(craftList, items) @@ -345,14 +370,17 @@ local function craftItems() jobListGrid:sync() for key, item in pairs(list) do if item.need > 0 and item.recipe then - craftItem(key, item, items) + craftItem(key, item, items, machineStatus) dock() items = getItems() -- should decrement count instead ... - jobListGrid:update() - jobListGrid:draw() - jobListGrid:sync() clearGrid() + elseif item.need > 0 then + item.status = 'no recipe' + item.statusCode = STATUS_WARNING end + jobListGrid:update() + jobListGrid:draw() + jobListGrid:sync() end end @@ -434,12 +462,13 @@ local function findMachines() end m.empty = m2.empty m.ignore = m2.ignore + m.maxCount = m2.maxCount end end end local function jobMonitor() - local mon = Peripheral.getByType('monitor') + local mon = Peripheral.lookup(config.monitor) if mon then mon = UI.Device({ @@ -463,10 +492,12 @@ local function jobMonitor() }) function jobListGrid:getRowTextColor(row, selected) - if row.status == '(no recipe)'then + if row.statusCode == STATUS_ERROR then return colors.red - elseif row.statusCode == 'missing' then + elseif row.statusCode == STATUS_WARNING then return colors.yellow + elseif row.statusCode == STATUS_SUCCESS then + return colors.lime end return UI.Grid:getRowTextColor(row, selected) @@ -793,6 +824,10 @@ local machinesPage = UI.Page { }, help = 'Check if machine is empty before crafting' }, + [4] = UI.TextEntry { + formLabel = 'Max Craft', formKey = 'maxCount', help = '...', + limit = 4, + }, }, statusBar = UI.StatusBar(), }, @@ -839,6 +874,7 @@ function machinesPage:eventHandler(event) elseif event.type == 'form_complete' then self.detail.form.values.empty = self.detail.form.values.empty == true self.detail.form.values.ignore = self.detail.form.values.ignore == true + self.detail.form.values.maxCount = tonumber(self.detail.form.values.maxCount) Util.writeTable(MACHINES_FILE, machines) self.detail:hide() @@ -1018,4 +1054,4 @@ Event.onInterval(30, function() end) UI:pullEvents() ---jobListGrid.parent:reset() +jobListGrid.parent:reset() diff --git a/apps/mwm.lua b/apps/mwm.lua index 98dda2f..590879e 100644 --- a/apps/mwm.lua +++ b/apps/mwm.lua @@ -22,7 +22,7 @@ local UID = 0 local multishell = { } local processes = { } local parentTerm = term.current() -local sessionFile = args[1] or 'config/mwm' +local sessionFile = args[1] or 'usr/config/mwm' local running local monitor diff --git a/apps/storageActivity.lua b/apps/storageActivity.lua index 92f42ac..2c9de7c 100644 --- a/apps/storageActivity.lua +++ b/apps/storageActivity.lua @@ -8,7 +8,7 @@ local Util = require('util') local colors = _G.colors local multishell = _ENV.multishell -local storage = InventoryAdapter.wrap({ autoDetect = true }) +local storage = InventoryAdapter.wrap() if not storage then error('Not connected to a valid inventory') end diff --git a/apps/termShare.lua b/apps/termShare.lua new file mode 100644 index 0000000..9ac5ae5 --- /dev/null +++ b/apps/termShare.lua @@ -0,0 +1,19 @@ +local device = _G.device +local multishell = _ENV.multishell +local os = _G.os +local term = _G.term + +-- list this terminal in the devices list so it's available via +-- peripheral sharing + +local args = { ... } +local name = args[1] or error('Syntax: termShare [device name]