From 57e7a574c49373ae570a69561af009496fe0ee2e Mon Sep 17 00:00:00 2001 From: kepler155c Date: Sat, 27 Oct 2018 21:35:21 -0400 Subject: [PATCH] milo wip --- milo/Milo.lua | 14 ++- milo/MiloRemote.lua | 27 ++-- milo/apis/milo.lua | 14 +++ milo/apis/storage.lua | 20 +-- milo/core/machines.lua | 186 ++++++++++++++++++++++++--- milo/plugins/exportTask.lua | 36 +++--- milo/plugins/exportView.lua | 228 +++++++++------------------------- milo/plugins/importTask.lua | 33 ++++- milo/plugins/importView.lua | 108 +++++++++++----- milo/plugins/jobList.lua | 2 +- milo/plugins/machineLearn.lua | 13 +- milo/plugins/redstoneTask.lua | 28 +++++ milo/plugins/redstoneView.lua | 73 +++++++++++ milo/plugins/remote.lua | 1 + milo/plugins/storageView.lua | 7 +- milo/plugins/turtleLearn.lua | 16 +-- 16 files changed, 518 insertions(+), 288 deletions(-) create mode 100644 milo/plugins/redstoneTask.lua create mode 100644 milo/plugins/redstoneView.lua diff --git a/milo/Milo.lua b/milo/Milo.lua index e902594..7256a09 100644 --- a/milo/Milo.lua +++ b/milo/Milo.lua @@ -85,6 +85,9 @@ if not modem or not modem.getNameLocal then error('Wired modem is not connected') end +local introspectionModule = Peripheral.get('plethora:introspection') or + error('Introspection module not found') + local function loadResources() local resources = Util.readTable(Milo.RESOURCE_FILE) or { } for k,v in pairs(resources) do @@ -98,12 +101,15 @@ local context = { config = config, resources = loadResources(), userRecipes = Util.readTable(Milo.RECIPES_FILE) or { }, - learnTypes = { }, - machineTypes = { }, - localName = modem.getNameLocal(), - tasks = { }, + craftingQueue = { }, + + learnTypes = { }, + tasks = { }, + + localName = modem.getNameLocal(), storage = Storage(config), + introspectionModule = introspectionModule, } _G._p = context --debug diff --git a/milo/MiloRemote.lua b/milo/MiloRemote.lua index 2b9830c..75fd5f3 100644 --- a/milo/MiloRemote.lua +++ b/milo/MiloRemote.lua @@ -9,7 +9,6 @@ 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', @@ -34,6 +33,11 @@ if not options.user.value or not options.server.value then error('Invalid arguments') end +if options.slot.value and + not (device.neuralInterface and device.neuralInterface.getInventory) then + error('Introspection module is required for transferring items') +end + local page = UI.Page { menuBar = UI.MenuBar { buttons = { @@ -240,14 +244,21 @@ function page:applyFilter() self.grid:setValues(t) end -if neural and options.slot.value and neural.getInventory then +if options.slot.value then + debug('Transfer items initialized') 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() + local neural = device.neuralInterface + if neural and neural.getInventory then + local item = neural.getInventory().getItem(options.slot.value) + if item then + debug('depositing') + page:sendRequest({ request = 'deposit', slot = options.slot.value }) + -- local item = + -- TODO: update count for this one item + -- page.grid:draw() page:sync() + end + else + debug('missing Introspection module') end end) end diff --git a/milo/apis/milo.lua b/milo/apis/milo.lua index f02401c..bcbbef8 100644 --- a/milo/apis/milo.lua +++ b/milo/apis/milo.lua @@ -129,6 +129,20 @@ function Milo:clearGrid() return clear() or clear() end +function Milo:getTurtleInventory() + local list = { } + for i = 1,16 do + -- TODO: update item db + local item = self.context.introspectionModule.getInventory().getItemMeta(i) + if item then + itemDB:add(item) + list[i] = item + end + end + itemDB:flush() + return list +end + function Milo:eject(item, qty) local s, m = pcall(function() self.context.storage:provide(item, qty) diff --git a/milo/apis/storage.lua b/milo/apis/storage.lua index ddb2f93..39ab696 100644 --- a/milo/apis/storage.lua +++ b/milo/apis/storage.lua @@ -23,17 +23,24 @@ listCount = 0, local modem = Peripheral.get('wired_modem') or error('Wired modem not attached') self.localName = modem.getNameLocal() - Event.on({ 'device_attach' }, function(_, dev) -debug('attach: ' .. dev) + Event.on({ 'device_attach', 'device_detach' }, function(e, dev) +debug('%s: %s', e, tostring(dev)) self:initStorage() end) - - Event.on({ 'device_detach' }, function(_, dev) -debug('detach: ' .. dev) - self:initStorage(dev) + Event.onInterval(15, function() + self:showStorage() end) end +function NetworkedAdapter:showStorage() + debug('Storage:') + for k,v in pairs(self.remoteDefaults) do + local online = v.adapter and v.adapter.online + debug(' %s: %s', online and ' online' or 'offline', k) + end + debug('') +end + function NetworkedAdapter:setOnline(online) if online ~= self.storageOnline then self.storageOnline = online @@ -59,7 +66,6 @@ function NetworkedAdapter:initStorage() end if v.mtype == 'storage' then online = online and not not (v.adapter and v.adapter.online) - debug(' %s: %s', v.adapter and v.adapter.online and ' online' or 'offline', k) end end diff --git a/milo/core/machines.lua b/milo/core/machines.lua index 10d3187..4201859 100644 --- a/milo/core/machines.lua +++ b/milo/core/machines.lua @@ -51,6 +51,22 @@ local machinesPage = UI.Page { }, } +function machinesPage.grid:getDisplayValues(row) + row = Util.shallowCopy(row) + row.displayName = row.displayName or row.name + return row +end + +function machinesPage.grid:getRowTextColor(row, selected) + if not device[row.name] then + return colors.red + end + if row.mtype == 'ignore' then + return colors.lightGray + end + return UI.Grid:getRowTextColor(row, selected) +end + function machinesPage:getList() -- TODO: remove dedupe naming in perf code ? for _, v in pairs(device) do @@ -82,22 +98,6 @@ function machinesPage:disable() Event.off(self.handler) end -function machinesPage.grid:getDisplayValues(row) - row = Util.shallowCopy(row) - row.displayName = row.displayName or row.name - return row -end - -function machinesPage.grid:getRowTextColor(row, selected) - if not device[row.name] then - return colors.red - end - if row.mtype == 'ignore' then - return colors.lightGray - end - return UI.Grid:getRowTextColor(row, selected) -end - function machinesPage:eventHandler(event) if event.type == 'grid_select' then UI:setPage('machineWizard', event.selected) @@ -178,8 +178,146 @@ The settings will take effect immediately!]], backgroundColor = colors.cyan, }, notification = UI.Notification { }, + filter = UI.SlideOut { + backgroundColor = colors.cyan, + menuBar = UI.MenuBar { + buttons = { + { text = 'Save', event = 'save' }, + { text = 'Cancel', event = 'cancel' }, + }, + }, + grid = UI.ScrollingGrid { + x = 2, ex = -6, y = 2, ey = -6, + columns = { + { heading = 'Name', key = 'displayName' }, + }, + sortColumn = 'displayName', + help = 'Select item to export', + }, + remove = UI.Button { + x = -4, y = 4, + text = '-', event = 'remove_entry', help = 'Remove', + }, + form = UI.Form { + x = 2, y = -4, height = 3, + margin = 1, + manualControls = true, + [1] = UI.Chooser { + width = 7, + formLabel = 'Ignore Dmg', formKey = 'ignoreDamage', + pruneEmpty = true, + nochoice = 'No', + choices = { + { name = 'Yes', value = true }, + { name = 'No', value = false }, + }, + help = 'Ignore damage of item when exporting' + }, + [2] = UI.Chooser { + width = 7, + formLabel = 'Ignore NBT', formKey = 'ignoreNbtHash', + pruneEmpty = true, + nochoice = 'No', + choices = { + { name = 'Yes', value = true }, + { name = 'No', value = false }, + }, + help = 'Ignore NBT of item when exporting' + }, + [3] = UI.Chooser { + width = 13, + formLabel = 'Mode', formKey = 'blacklist', + nochoice = 'whitelist', + choices = { + { name = 'whitelist', value = false }, + { name = 'blacklist', value = true }, + }, + help = 'Ignore damage of item when exporting' + }, + scan = UI.Button { + x = -11, y = 1, + text = 'Scan', event = 'scan_turtle', + help = 'Add items to turtle to add to filter', + }, + }, + statusBar = UI.StatusBar { + backgroundColor = colors.cyan, + }, + }, } +--[[ Filter slide out ]] -- +function machineWizard.filter:show(entry, callback, whitelistOnly) + self.entry = entry + self.callback = callback + + if not self.entry.filter then + self.entry.filter = { } + end + + self.form:setValues(entry) + self:resetGrid() + + self.form[3].inactive = whitelistOnly + + UI.SlideOut.show(self) +-- self:setFocus(self.filter) +end + +function machineWizard.filter:resetGrid() + local t = { } + for k in pairs(self.entry.filter) do + table.insert(t, itemDB:splitKey(k)) + end + self.grid:setValues(t) +end + +function machineWizard.filter.grid:getDisplayValues(row) + row = Util.shallowCopy(row) + row.displayName = itemDB:getName(row) + return row +end + +function machineWizard.filter:eventHandler(event) + if event.type == 'focus_change' then + self.statusBar:setStatus(event.focused.help) + + elseif event.type == 'scan_turtle' then + local inventory = Milo:getTurtleInventory() + for _,item in pairs(inventory) do + self.entry.filter[Milo:uniqueKey(item)] = true + end + self:resetGrid() + self.grid:update() + self.grid:draw() + + elseif event.type == 'remove_entry' then + local row = self.grid:getSelected() + if row then + Util.removeByValue(self.grid.values, row) + self.grid:update() + self.grid:draw() + end + + elseif event.type == 'save' then + self.form:save() + self.entry.filter = { } + for _,v in pairs(self.grid.values) do + self.entry.filter[Milo:uniqueKey(v)] = true + end + self:hide() + self.callback() + + elseif event.type == 'cancel' then + self:hide() + + else + return UI.SlideOut.eventHandler(self, event) + end + return true +end + +--[[ General Page ]] -- function machineWizard.wizard.pages.general:enable() UI.Window.enable(self) self:focusFirst() @@ -208,6 +346,7 @@ function machineWizard.wizard.pages.general:validate() return self.form:save() end +--[[ Wizard ]] -- function machineWizard.wizard:eventHandler(event) if event.type == 'nextView' and Util.find(self.pages, 'enabled', true) == self.pages.general then @@ -215,11 +354,16 @@ function machineWizard.wizard:eventHandler(event) if self.pages.general.form:save() then local index = 2 for _, page in pairs(self.pages) do - if page.mtype == machineWizard.machine.mtype then + page.index = nil + end + self.pages.general.index = 1 + self.pages.confirmation.index = 2 + + for k, page in pairs(self.pages) do +debug(k) + if not page.index and page:isValidFor(self.parent.machine) then page.index = index index = index + 1 - elseif page.index ~= 1 then - page.index = nil end end self.pages.confirmation.index = index @@ -237,6 +381,7 @@ function machineWizard:enable(machine) self.machine.adapter = adapter machine.adapter = adapter +_G._p2 = self.machine self.wizard.pages.general.form:setValues(self.machine) self.wizard.pages.general.form[1].shadowText = self.machine.name @@ -286,6 +431,9 @@ function machineWizard:eventHandler(event) UI:setPreviousPage() + elseif event.type == 'edit_filter' then + self.filter:show(event.entry, event.callback, event.whitelistOnly) + elseif event.type == 'enable_view' then local current = event.next or event.prev self.titleBar.title = current.title or 'Machine' diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index b8314e6..8d2eec4 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -14,22 +14,30 @@ function ExportTask:cycle(context) local machine = device[target] if machine and machine.getItemMeta then for _, entry in pairs(v.exports) do - local slot = machine.getItemMeta(entry.slot) or { count = 0 } - local item = itemDB:splitKey(entry.name) + local slotNo = type(entry.slot) == 'number' and entry.slot or nil -- '*' indicates any slot - -- is something else is in this slot - if not slot.name or slot.name == item.name then - local maxCount = slot.maxCount or itemDB:getMaxCount(item) - local count = maxCount - slot.count + local slot = (slotNo and machine.getItemMeta(slotNo)) or { count = 0 } + for key in pairs(entry.filter) do + local item = itemDB:splitKey(key) - if count > 0 then - item = Milo:getItemWithQty(item) - if item and count > 0 then - context.storage:export( - target, - entry.slot, - math.min(count, item.count), - item) + -- is something else is in this slot + if not slot.name or slot.name == item.name then + local maxCount = slot.maxCount or itemDB:getMaxCount(item) + local count = maxCount - slot.count + if not slotNo then + -- TODO: should we just execute export - + -- or scan all slots for space ?? + count = machine.size() * maxCount - slot.count + end + if count > 0 then + item = Milo:getItemWithQty(item) + if item and count > 0 then + context.storage:export( + target, + slotNo, + math.min(count, item.count), + item) + end end end end diff --git a/milo/plugins/exportView.lua b/milo/plugins/exportView.lua index 43a5108..d231e27 100644 --- a/milo/plugins/exportView.lua +++ b/milo/plugins/exportView.lua @@ -1,181 +1,43 @@ local itemDB = require('itemDB') -local Milo = require('milo') local UI = require('ui') local Util = require('util') -local colors = _G.colors local device = _G.device -local itemSlideout = UI.SlideOut { - backgroundColor = colors.cyan, - menuBar = UI.MenuBar { - buttons = { - { text = 'Save', event = 'save' }, - { text = 'Cancel', event = 'cancel' }, - { text = 'Refresh', event = 'refresh', x = -9 }, - }, - }, - grid = UI.ScrollingGrid { - y = 2, ey = -6, - columns = { - { heading = 'Name', key = 'displayName', width = 31 }, - { heading = 'Qty', key = 'count' , width = 5 }, - }, - sortColumn = 'displayName', - help = 'Select item to export', - }, - filter = UI.TextEntry { - x = 2, ex = 18, y = -3, - limit = 50, - shadowText = 'filter', - backgroundColor = colors.lightGray, - backgroundFocusColor = colors.lightGray, - }, - form = UI.Form { - x = 21, y = -4, height = 3, - margin = 1, - manualControls = true, - [1] = UI.Chooser { - width = 7, - formLabel = 'Slot', formKey = 'slot', - nochoice = 1, - help = 'Export into this slot', - }, - [2] = UI.Chooser { - width = 7, - formLabel = 'Ignore Dmg', formKey = 'ignoreDamage', - pruneEmpty = true, - nochoice = 'No', - choices = { - { name = 'Yes', value = true }, - { name = 'No', value = false }, - }, - help = 'Ignore damage of item when exporting' - }, - [3] = UI.Chooser { - width = 7, - formLabel = 'Ignore NBT', formKey = 'ignoreNbtHash', - pruneEmpty = true, - nochoice = 'No', - choices = { - { name = 'Yes', value = true }, - { name = 'No', value = false }, - }, - help = 'Ignore NBT of item when exporting' - }, - }, - statusBar = UI.StatusBar { - backgroundColor = colors.cyan, - }, -} - -function itemSlideout:filterItems(t, filter) - if filter and #filter > 0 then - local r = {} - filter = filter:lower() - for _,v in pairs(t) do - if string.find(v.lname, filter) then - table.insert(r, v) - end - end - return r - end - return t -end - -function itemSlideout.grid:enable() - if not self.allItems then - self.allItems = Milo:listItems() - Milo:mergeResources(self.allItems) - self:setValues(self.allItems) - end - UI.Grid.enable(self) -end - -function itemSlideout:show(machine, entry, callback) - self.entry = entry - self.callback = callback - - self.form.choices = { } - local m = device[machine.name] - for k = 1, m.size() do - table.insert(self.form[1].choices, { - name = k, - value = k, - }) - end - - if not entry.slot then - entry.slot = 1 - end - self.form:setValues(entry) - - UI.SlideOut.show(self) - self:setFocus(self.filter) - --self.filter:focus() -end - -function itemSlideout:eventHandler(event) - if event.type == 'text_change' then - local t = self:filterItems(self.grid.allItems, event.text) - self.grid:setValues(t) - self.grid:draw() - - elseif event.type == 'focus_change' then - self.statusBar:setStatus(event.focused.help) - - elseif event.type == 'save' then - local selected = self.grid:getSelected() - if not selected then - self.statusBar:setStatus('Select an item to export') - else - self.form:save() - self.form.values.name = itemDB:makeKey(selected) - self:hide() - self.callback() - end - - elseif event.type == 'cancel' then - self:hide() - - elseif event.type == 'refresh' then - self.allItems = Milo:listItems() - Milo:mergeResources(self.allItems) - local t = self:filterItems(self.allItems, self.filter.value) - self.grid:setValues(t) - self.grid:draw() - self.filter:focus() - else - return UI.SlideOut.eventHandler(self, event) - end - return true -end - local exportView = UI.Window { - mtype = 'machine', title = 'Export item into machine', index = 3, grid = UI.ScrollingGrid { - x = 2, ex = -6, y = 2, ey = -2, + x = 2, ex = -6, y = 2, ey = -4, columns = { - { heading = 'Slot', key = 'slot', width = 4 }, - { heading = 'Item', key = 'displayName' }, + { heading = 'Slot', key = 'slot', width = 4 }, + { heading = 'Filter', key = 'filter' }, }, sortColumn = 'slot', + help = 'Edit this entry', + }, + text = UI.Text { + x = 2, y = -2, + value = 'Slot', + }, + slots = UI.Chooser { + x = 7, y = -2, + width = 7, + nochoice = 'All', + help = 'Export to this slot', }, add = UI.Button { - x = -4, y = 4, - text = '+', event = 'add_export', help = '...', + x = 15, y = -2, + text = '+', event = 'add_entry', help = 'Add', }, remove = UI.Button { - x = -4, y = 6, - text = '-', event = 'remove_export', help = '...', + x = -4, y = 4, + text = '-', event = 'remove_entry', help = 'Remove', }, } -function exportView:save(machine) - machine.exports = not Util.empty(self.grid.values) and self.grid.values or nil - return true +function exportView:isValidFor(machine) + return machine.mtype == 'machine' end function exportView:setMachine(machine) @@ -184,30 +46,53 @@ function exportView:setMachine(machine) self.machine.exports = { } end self.grid:setValues(machine.exports) + + self.slots.choices = { + { name = 'All', value = '*' } + } + + -- TODO: what if device is dettached ? + local m = device[machine.name] + for k = 1, m.size() do + table.insert(self.slots.choices, { name = k, value = k }) + end end function exportView.grid:getDisplayValues(row) row = Util.shallowCopy(row) - row.displayName = itemDB:getName(row.name) + if not row.filter or Util.empty(row.filter) then + row.filter = 'none' + else + local t = { } + for key in pairs(row.filter) do + table.insert(t, itemDB:getName(key)) + end + row.filter = table.concat(t, ', ') + end return row end function exportView:eventHandler(event) if event.type == 'grid_select' then - itemSlideout:show(self.machine, self.grid:getSelected(), function() - self.grid:update() - self.grid:draw() - end) + self:emit({ + type = 'edit_filter', + entry = self.grid:getSelected(), + whitelistOnly = true, + callback = function() + self.grid:update() + self.grid:draw() + end, + }) - elseif event.type == 'add_export' then - local export = { } - itemSlideout:show(self.machine, export, function() - table.insert(self.machine.exports, export) - self.grid:update() - self.grid:draw() - end) + elseif event.type == 'add_entry' then + table.insert(self.machine.exports, { + slot = self.slots.value or '*', + filter = { }, + }) + self.grid:update() + self.grid:draw() - elseif event.type == 'remove_export' then + elseif event.type == 'remove_entry' then local row = self.grid:getSelected() if row then Util.removeByValue(self.grid.values, row) @@ -217,5 +102,4 @@ function exportView:eventHandler(event) end end -UI:getPage('machineWizard'):add({ items = itemSlideout }) UI:getPage('machineWizard').wizard:add({ export = exportView }) diff --git a/milo/plugins/importTask.lua b/milo/plugins/importTask.lua index 6020a7e..0e26156 100644 --- a/milo/plugins/importTask.lua +++ b/milo/plugins/importTask.lua @@ -11,11 +11,34 @@ function ImportTask:cycle(context) for source, v in pairs(context.config.remoteDefaults) do if v.imports then local inventory = device[source] - if inventory and inventory.getItemMeta then - for slot in pairs(v.imports) do - local item = inventory.getItemMeta(slot) - if item then - context.storage:import(source, slot, item.count, item) + if inventory then + for _, entry in pairs(v.imports) do + + local function matchesFilter(item) + if not entry.filter then + return true + end + + local key = Milo:uniqueKey(item) + if entry.blacklist then + return not entry.filter[key] + end + return entry.filter[key] + end + + local function importSlot(slotNo) + local item = inventory.getItemMeta(slotNo) + if item and matchesFilter(item) then + context.storage:import(source, slotNo, item.count, item) + end + end + + if type(entry.slot) == 'number' then + importSlot(entry.slot) + else + for i = 1, inventory.size() do + importSlot(i) + end end end else diff --git a/milo/plugins/importView.lua b/milo/plugins/importView.lua index 92abe68..38a4dac 100644 --- a/milo/plugins/importView.lua +++ b/milo/plugins/importView.lua @@ -1,55 +1,103 @@ -local UI = require('ui') -local Util = require('util') +local itemDB = require('itemDB') +local UI = require('ui') +local Util = require('util') local device = _G.device local importView = UI.Window { - mtype = 'machine', title = 'Import item from machine', index = 4, grid = UI.ScrollingGrid { - y = 2, ey = -2, + x = 2, ex = -6, y = 2, ey = -4, columns = { { heading = 'Slot', key = 'slot', width = 4 }, - { heading = 'Import', key = 'import' }, + { heading = 'Filter', key = 'filter' }, }, sortColumn = 'slot', - help = 'Double-click to toggle' + help = 'Edit this entry', + }, + text = UI.Text { + x = 2, y = -2, + value = 'Slot', + }, + slots = UI.Chooser { + x = 7, y = -2, + width = 7, + nochoice = 'All', + help = 'Import from this slot', + }, + add = UI.Button { + x = 15, y = -2, + text = '+', event = 'add_entry', help = 'Add', + }, + remove = UI.Button { + x = -4, y = 4, + text = '-', event = 'remove_entry', help = 'Remove', }, } -function importView:setMachine(machine) - local m = device[machine.name] - - local t = { } - for k = 1, m.size() do - t[k] = { slot = k } - end - - if machine.imports then - for k,v in pairs(machine.imports) do - t[k] = { slot = k, import = v } - end - end - - self.grid:setValues(t) +function importView:isValidFor(machine) + return machine.mtype == 'machine' end -function importView:save(machine) - local t = { } - for k,v in pairs(self.grid.values) do - if v.import then - t[k] = true - end +function importView:setMachine(machine) + self.machine = machine + if not self.machine.imports then + self.machine.imports = { } end - machine.imports = not Util.empty(t) and t or nil - return true + self.grid:setValues(machine.imports) + + self.slots.choices = { + { name = 'All', value = '*' } + } + + -- TODO: what if device is dettached ? + local m = device[machine.name] + for k = 1, m.size() do + table.insert(self.slots.choices, { name = k, value = k }) + end +end + +function importView.grid:getDisplayValues(row) + row = Util.shallowCopy(row) + if not row.filter or Util.empty(row.filter) then + row.filter = 'none' + else + local t = { } + for key in pairs(row.filter) do + table.insert(t, itemDB:getName(key)) + end + row.filter = table.concat(t, ', ') + end + return row end function importView:eventHandler(event) if event.type == 'grid_select' then - event.selected.import = not event.selected.import + self:emit({ + type = 'edit_filter', + entry = self.grid:getSelected(), + callback = function() + self.grid:update() + self.grid:draw() + end, + }) + + elseif event.type == 'add_entry' then + table.insert(self.machine.imports, { + slot = self.slots.value or '*', + filter = { }, + }) + self.grid:update() self.grid:draw() + + elseif event.type == 'remove_entry' then + local row = self.grid:getSelected() + if row then + Util.removeByValue(self.grid.values, row) + self.grid:update() + self.grid:draw() + end end end diff --git a/milo/plugins/jobList.lua b/milo/plugins/jobList.lua index 7a5b9e1..4862d3a 100644 --- a/milo/plugins/jobList.lua +++ b/milo/plugins/jobList.lua @@ -61,7 +61,7 @@ end function jobList.grid:getDisplayValues(row) row = Util.shallowCopy(row) if row.showRemaining then - row.remaining = row.count - row.crafted + row.remaining = math.max(0, row.count - row.crafted) else row.displayName = ' ' .. row.displayName end diff --git a/milo/plugins/machineLearn.lua b/milo/plugins/machineLearn.lua index d005c92..1af4b46 100644 --- a/milo/plugins/machineLearn.lua +++ b/milo/plugins/machineLearn.lua @@ -12,17 +12,6 @@ local MACHINE_LOOKUP = 'usr/config/machine_crafting.db' local context = Milo:getContext() -local function getTurtleInventory() - local introspectionModule = device['plethora:introspection'] or - error('Introspection module not found') - - local list = { } - for i = 1,16 do - list[i] = introspectionModule.getInventory().getItemMeta(i) - end - return list -end - local machineLearnWizard = UI.Page { titleBar = UI.TitleBar { title = 'Learn a crafting recipe' }, wizard = UI.Wizard { @@ -92,7 +81,7 @@ function pages.machine:validate() end function pages.confirmation:validate() - local inventory = getTurtleInventory() + local inventory = Milo:getTurtleInventory() local result = inventory[16] local slotCount = machine.size() diff --git a/milo/plugins/redstoneTask.lua b/milo/plugins/redstoneTask.lua new file mode 100644 index 0000000..4cc0a09 --- /dev/null +++ b/milo/plugins/redstoneTask.lua @@ -0,0 +1,28 @@ +local Event = require('event') +local Milo = require('milo') + +local device = _G.device + +local RedstoneTask = { + name = 'redstone', + priority = 40, +} + +function RedstoneTask:cycle(context) + for _,v in pairs(context.config.remoteDefaults) do + if v.redstone then + local ri = device[v.redstone.integrator] + local function conditionsSatisfied() + return not not next(ri.list()) + end + if conditionsSatisfied() then + ri.setOutput(v.redstone.side, true) + Event.onTimeout(.25, function() + ri.setOutput(v.redstone.side, false) + end) + end + end + end +end + +Milo:registerTask(RedstoneTask) diff --git a/milo/plugins/redstoneView.lua b/milo/plugins/redstoneView.lua new file mode 100644 index 0000000..0ed3dfc --- /dev/null +++ b/milo/plugins/redstoneView.lua @@ -0,0 +1,73 @@ +local UI = require('ui') + +local colors = _G.colors +local device = _G.device + +local dispenserView = UI.Window { + index = 10, + title = 'Redstone Control', + backgroundColor = colors.cyan, + form = UI.Form { + x = 1, y = 2, ex = -1, ey = -2, + manualControls = true, + [1] = UI.TextEntry { + formLabel = 'Interval', formKey = 'interval', + help = 'Pulse redstone if items are present', + limit = 6, + validate = 'numeric', + }, + [2] = UI.Chooser { + formLabel = 'Integrator', formKey = 'integrator', + nochoice = 'disable', + help = 'Control via redstone', + }, + [3] = UI.Chooser { + width = 10, + formLabel = 'Side', formKey = 'side', + choices = { + { name = 'up', value = 'up' }, + { name = 'down', value = 'down' }, + { name = 'east', value = 'east' }, + { name = 'north', value = 'north' }, + { name = 'west', value = 'west' }, + { name = 'south', value = 'south' }, + }, + help = 'Output side', + }, + }, +} + +function dispenserView:isValidFor(machine) + if machine.mtype == 'machine' then + local m = device[machine.name] + return m and m.type == 'minecraft:dispenser' + end +end + +function dispenserView:enable() + UI.Window.enable(self) + self:focusFirst() + + self.form[2].choices = { } + for _,m in pairs(device) do + if m.type == 'redstone_integrator' then + table.insert(self.form[2].choices, { + name = m.name, + value = m.name, + }) + end + end +end + +function dispenserView:validate() + return self.form:save() +end + +function dispenserView:setMachine(machine) + if not machine.redstone then + machine.redstone = { } + end + self.form:setValues(machine.redstone) +end + +UI:getPage('machineWizard').wizard:add({ dispenser = dispenserView }) diff --git a/milo/plugins/remote.lua b/milo/plugins/remote.lua index 28d00e2..0869c27 100644 --- a/milo/plugins/remote.lua +++ b/milo/plugins/remote.lua @@ -33,6 +33,7 @@ local function client(socket) if not data then break end +debug('remote: ' .. data.request) if data.request == 'list' then local items = Milo:refreshItems() Milo:mergeResources(items) diff --git a/milo/plugins/storageView.lua b/milo/plugins/storageView.lua index 78af345..e13622b 100644 --- a/milo/plugins/storageView.lua +++ b/milo/plugins/storageView.lua @@ -1,11 +1,10 @@ local itemDB = require('itemDB') -local UI = require('ui') +local UI = require('ui') local colors = _G.colors local device = _G.device local storageView = UI.Window { - mtype = 'storage', title = 'Storage Options', index = 2, backgroundColor = colors.cyan, @@ -49,6 +48,10 @@ function storageView:validate() return self.form:save() end +function storageView:isValidFor(machine) + return machine.mtype == 'storage' +end + function storageView:setMachine(machine) self.machine = machine self.form:setValues(machine) diff --git a/milo/plugins/turtleLearn.lua b/milo/plugins/turtleLearn.lua index 6897035..65bd47f 100644 --- a/milo/plugins/turtleLearn.lua +++ b/milo/plugins/turtleLearn.lua @@ -4,24 +4,12 @@ local Milo = require('milo') local UI = require('ui') local Util = require('util') -local device = _G.device local turtle = _G.turtle local context = Milo:getContext() -local function getTurtleInventory() - local introspectionModule = device['plethora:introspection'] or - error('Introspection module not found') - - local list = { } - for i = 1,16 do - list[i] = introspectionModule.getInventory().getItemMeta(i) - end - return list -end - local function learnRecipe() - local ingredients = getTurtleInventory() + local ingredients = Milo:getTurtleInventory() if not ingredients then return false, 'No recipe defined' @@ -32,7 +20,7 @@ local function learnRecipe() return false, 'Failed to craft' end - local results = getTurtleInventory() + local results = Milo:getTurtleInventory() if not results or not results[1] then return false, 'Failed to craft' end