diff --git a/milo/Milo.lua b/milo/Milo.lua index 5db66ba..88c06f9 100644 --- a/milo/Milo.lua +++ b/milo/Milo.lua @@ -198,12 +198,11 @@ Milo:clearGrid() local page = UI:getPage('listing') UI:setPage(page) -page:setFocus(page.statusBar.filter) -- todo: move this line into listing code Event.onInterval(5, function() if not Milo:isCraftingPaused() then Milo:resetCraftingStatus() - context.inventoryAdapter:refresh() + Milo:refreshItems() for _, task in ipairs(context.tasks) do local s, m = pcall(function() task:cycle(context) end) diff --git a/milo/MiloMonitor.lua b/milo/MiloMonitor.lua index c36d4f2..1e59828 100644 --- a/milo/MiloMonitor.lua +++ b/milo/MiloMonitor.lua @@ -6,7 +6,7 @@ local colors = _G.colors local device = _G.device local args = { ... } -local mon = device[args[1] or 'monitor'] or error('Syntax: debug ') +local mon = device[args[1] or 'monitor'] or error('Syntax: MiloMonitor ') local config = Util.readTable('/usr/config/milo') or error('Milo is not configured') local row diff --git a/milo/MiloRemote.lua b/milo/MiloRemote.lua index cd9403d..2b9830c 100644 --- a/milo/MiloRemote.lua +++ b/milo/MiloRemote.lua @@ -1,18 +1,24 @@ _G.requireInjector(_ENV) +local Event = require('event') local Socket = require('socket') +local sync = require('sync') local UI = require('ui') local Util = require('util') local colors = _G.colors +local device = _G.device local socket +local neural = device.neuralInterface local options = { user = { arg = 'u', type = 'string', desc = 'User name associated with bound manipulator' }, - server = { arg = 's', type = 'number', + slot = { arg = 's', type = 'number', + desc = 'Optional inventory slot to use to transfer to milo' }, + server = { arg = 'm', type = 'number', desc = 'ID of Milo server' }, - help = { arg = 'h', type = 'flag', value = false, + help = { arg = 'h', type = 'flag', value = false, desc = 'Displays the options' }, } @@ -107,26 +113,31 @@ local function filterItems(t, filter, displayMode) end function page:sendRequest(data) - local msg + local response - for _ = 1, 2 do - if not socket or not socket.connected then - socket, msg = Socket.connect(options.server.value, 4242) - if socket then - socket:write(options.user.value) - end - end - if socket then - if socket:write(data) then - local response = socket:read(2) - if response then - return response + sync(self, function() + local msg + for _ = 1, 2 do + if not socket or not socket.connected then + socket, msg = Socket.connect(options.server.value, 4242) + if socket then + socket:write(options.user.value) end end - socket:close() + if socket then + if socket:write(data) then + response = socket:read(2) + if response then + return + end + end + socket:close() + end end - end - self.notification:error(msg or 'Failed to connect') + self.notification:error(msg or 'Failed to connect') + end) + + return response end function page.statusBar:draw() @@ -162,23 +173,17 @@ function page:eventHandler(event) elseif event.type == 'eject' then local item = self.grid:getSelected() if item then - local items = self:sendRequest({ request = 'transfer', item = item, count = 1 }) - if items then - self.items = items - self:applyFilter() - self.grid:draw() - end + local response = self:sendRequest({ request = 'transfer', item = item, count = 1 }) + item.count = item.count - response.count + self.grid:draw() end elseif event.type == 'eject_stack' then local item = self.grid:getSelected() if item then - local items = self:sendRequest({ request = 'transfer', item = item, count = 64 }) - if items then - self.items = items - self:applyFilter() - self.grid:draw() - end + local response = self:sendRequest({ request = 'transfer', item = item, count = 64 }) + item.count = item.count - response.count + self.grid:draw() end elseif event.type == 'refresh' then @@ -235,6 +240,18 @@ function page:applyFilter() self.grid:setValues(t) end +if neural and options.slot.value and neural.getInventory then + Event.onInterval(1, function() + local inv = neural.getInventory() + if inv and inv.getItem(options.slot.value) then + page:sendRequest({ request = 'deposit', slot = options.slot.value }) + -- local item = + -- TODO: update count for this one item + -- page.grid:draw() page:sync() + end + end) +end + UI:setPage(page) UI:pullEvents() diff --git a/milo/apis/milo.lua b/milo/apis/milo.lua index 378cd71..f4b8439 100644 --- a/milo/apis/milo.lua +++ b/milo/apis/milo.lua @@ -25,7 +25,6 @@ function Milo:requestCrafting(item) item.ingredients = { [ key ] = item } --- item.ingredients[key] = item item.crafted = 0 self.context.craftingQueue[key] = item end @@ -66,17 +65,11 @@ function Milo:uniqueKey(item) end function Milo:resetCraftingStatus() - - -- todo: move to end of processing tasks ? - -- what if someone hoppers in items ? -- this shouldnt be allowed - -- all items must come in via pullItems self.context.inventoryAdapter.activity = { } for _,key in pairs(Util.keys(self.context.craftingQueue)) do local item = self.context.craftingQueue[key] if item.crafted >= item.count then - debug('removing:') - debug(item) self.context.craftingQueue[key] = nil end end @@ -204,4 +197,9 @@ function Milo:listItems() return self.context.inventoryAdapter:listItems() end +-- force a full rescan of chests +function Milo:refreshItems() + return self.context.inventoryAdapter:refresh() +end + return Milo diff --git a/milo/apis/turtle/craft.lua b/milo/apis/turtle/craft.lua index be62582..ac2fe8f 100644 --- a/milo/apis/turtle/craft.lua +++ b/milo/apis/turtle/craft.lua @@ -188,6 +188,7 @@ function Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) if canCraft == 0 then local resourceList = Craft.getResourceList(recipe, items, count) +_G._p2 = resourceList for k,v in pairs(resourceList) do if v.need > 0 then if not origItem.ingredients[k] then diff --git a/milo/core/machines.lua b/milo/core/machines.lua index 18d03b5..ef1394f 100644 --- a/milo/core/machines.lua +++ b/milo/core/machines.lua @@ -253,7 +253,7 @@ function machineWizard:eventHandler(event) elseif event.type == 'focus_change' then self.statusBar:setStatus(event.focused.help) - elseif event.type == 'form_invalid' then + elseif event.type == 'form_invalid' or event.type == 'general_error' then self.notification:error(event.message) self:setFocus(event.field) diff --git a/milo/plugins/craftTask.lua b/milo/plugins/craftTask.lua index 7cd499a..0ff8a84 100644 --- a/milo/plugins/craftTask.lua +++ b/milo/plugins/craftTask.lua @@ -70,6 +70,7 @@ function craftTask:forceCraftItem(inRecipe, originalItem, inCount) end end end + if craftable > 0 then craftable = Craft.craftRecipe(recipe, craftable * recipe.count, context.inventoryAdapter, originalItem) / recipe.count diff --git a/milo/plugins/exportView.lua b/milo/plugins/exportView.lua index 6bd20da..43a5108 100644 --- a/milo/plugins/exportView.lua +++ b/milo/plugins/exportView.lua @@ -132,7 +132,6 @@ function itemSlideout:eventHandler(event) self.form:save() self.form.values.name = itemDB:makeKey(selected) self:hide() - debug('calling cllbck') self.callback() end diff --git a/milo/plugins/item.lua b/milo/plugins/item.lua index c315296..3ef6200 100644 --- a/milo/plugins/item.lua +++ b/milo/plugins/item.lua @@ -36,24 +36,12 @@ local itemPage = UI.Page { help = 'Craft until out of ingredients' }, ]] - [4] = UI.Chooser { - width = 7, + [4] = UI.Checkbox { formLabel = 'Ignore Dmg', formKey = 'ignoreDamage', - nochoice = 'No', - choices = { - { name = 'Yes', value = true }, - { name = 'No', value = false }, - }, help = 'Ignore damage of item' }, - [5] = UI.Chooser { - width = 7, + [5] = UI.Checkbox { formLabel = 'Ignore NBT', formKey = 'ignoreNbtHash', - nochoice = 'No', - choices = { - { name = 'Yes', value = true }, - { name = 'No', value = false }, - }, help = 'Ignore NBT of item' }, --[[ diff --git a/milo/plugins/jobList.lua b/milo/plugins/jobList.lua index 93ed3a8..7a5b9e1 100644 --- a/milo/plugins/jobList.lua +++ b/milo/plugins/jobList.lua @@ -23,8 +23,7 @@ local jobList = UI.Page { { heading = 'Qty', key = 'remaining', width = 4 }, { heading = 'Crafting', key = 'displayName', }, { heading = 'Status', key = 'status', }, - { heading = 'Req', key = 'count', width = 3 }, - { heading = 'Cra', key = 'crafted', width = 3 }, + { heading = 'Progress', key = 'progress', width = 8 }, }, }, } @@ -66,6 +65,7 @@ function jobList.grid:getDisplayValues(row) else row.displayName = ' ' .. row.displayName end + row.progress = string.format('%d/%d', row.crafted, row.count) return row end diff --git a/milo/plugins/listing.lua b/milo/plugins/listing.lua index 2a941a6..f4b9023 100644 --- a/milo/plugins/listing.lua +++ b/milo/plugins/listing.lua @@ -40,9 +40,10 @@ end local listingPage = UI.Page { menuBar = UI.MenuBar { buttons = { - { text = 'Learn', event = 'learn' }, - { text = 'Forget', event = 'forget' }, - { text = 'Craft', event = 'craft' }, + { text = 'Learn', event = 'learn' }, + { text = 'Forget', event = 'forget' }, + { text = 'Craft', event = 'craft' }, + { text = '...', event = 'machines' }, { text = 'Refresh', event = 'refresh', x = -9 }, }, }, @@ -134,7 +135,12 @@ function listingPage:eventHandler(event) elseif event.type == 'eject' then local item = self.grid:getSelected() if item then - queue(function() Milo:eject(item, 1) end) + queue(function() + Milo:eject(item, 1) + local updated = Milo:getItem(Milo:listItems(), item) + item.count = updated and updated.count or 0 + self.grid:draw() + end) end elseif event.type == 'eject_stack' then @@ -225,7 +231,7 @@ function listingPage:enable() end function listingPage:refresh() - self.allItems = context.inventoryAdapter:refresh() + self.allItems = Milo:refreshItems() Milo:mergeResources(self.allItems) self:applyFilter() end diff --git a/milo/plugins/remote.lua b/milo/plugins/remote.lua index b0b0088..b517dcc 100644 --- a/milo/plugins/remote.lua +++ b/milo/plugins/remote.lua @@ -34,12 +34,20 @@ local function client(socket) break end if data.request == 'list' then - local items = Milo:listItems() + local items = Milo:refreshItems() Milo:mergeResources(items) socket:write(items) + elseif data.request == 'deposit' then + local count = manipulator.getInventory().pushItems( + context.localName, + data.slot, + 64) + socket:write({ count = count }) + Milo:clearGrid() + elseif data.request == 'transfer' then - context.inventoryAdapter:provide( + local count = context.inventoryAdapter:provide( data.item, data.count, nil, @@ -52,9 +60,7 @@ local function client(socket) slot.count) end) - local items = Milo:listItems() - Milo:mergeResources(items) - socket:write(items) + socket:write({ count = count }) end until not socket.connected diff --git a/milo/plugins/replenishTask.lua b/milo/plugins/replenishTask.lua index d204245..bed7987 100644 --- a/milo/plugins/replenishTask.lua +++ b/milo/plugins/replenishTask.lua @@ -30,7 +30,13 @@ function ReplenishTask:cycle(context) count = res.low - item.count, name = item.name, displayName = item.displayName, + replenish = true, }) + else + local request = context.craftingQueue[Milo:uniqueKey(item)] + if request and request.replenish then + request.count = request.crafted + end end end end diff --git a/milo/plugins/storageView.lua b/milo/plugins/storageView.lua index 9a855bd..78af345 100644 --- a/milo/plugins/storageView.lua +++ b/milo/plugins/storageView.lua @@ -1,6 +1,8 @@ +local itemDB = require('itemDB') local UI = require('ui') local colors = _G.colors +local device = _G.device local storageView = UI.Window { mtype = 'storage', @@ -16,14 +18,24 @@ local storageView = UI.Window { limit = 4, validate = 'numeric', pruneEmpty = true, }, - [2] = UI.TextEntry { - formLabel = 'Lock to', formKey = 'lockWith', + [2] = UI.Checkbox { + formLabel = 'Locked', formKey = 'lockWith', help = 'Locks chest to a single item type', - width = 18, limit = 64, pruneEmpty = true, + pruneEmpty = true, }, - [3] = UI.Button { - x = -9, ey = -4, - text = 'Detect', help = 'Determine what is currently present', + [3] = UI.Text { + x = 16, ex = -2, y = 3, + value = 'minecraft:xxxxx:0' + }, + [4] = UI.Checkbox { + formLabel = 'Void', formKey = 'voidExcess', + help = 'Void excess if locked - TODO', + pruneEmpty = true, + }, + [5] = UI.Checkbox { + formLabel = 'Partition', formKey = 'voidExcess', + help = 'TODO', + pruneEmpty = true, }, }, } @@ -38,7 +50,33 @@ function storageView:validate() end function storageView:setMachine(machine) + self.machine = machine self.form:setValues(machine) + self.form[3].value = machine.lock and itemDB:getName(machine.lock) or '' +end + +function storageView:eventHandler(event) + if event.type == 'checkbox_change' and event.element.formKey == 'lockWith' then + if event.checked then + if device[self.machine.name] and device[self.machine.name].list then + local _, slot = next(device[self.machine.name].list()) + if slot then + self.machine.lock = itemDB:makeKey(slot) + self.form[3].value = itemDB:getName(slot) + else + self:emit({ + type = 'general_error', + field = event.element, + message = 'The chest must contain the item to lock' }) + self.form[3].value = false + end + end + else + self.machine.lock = nil + self.form[3].value = '' + end + self.form[3]:draw() + end end UI:getPage('machineWizard').wizard:add({ storage = storageView })