diff --git a/builder/apis/builder/schematic.lua b/builder/apis/builder/schematic.lua index b530ee2..43228d2 100644 --- a/builder/apis/builder/schematic.lua +++ b/builder/apis/builder/schematic.lua @@ -23,7 +23,7 @@ local gzipMagic = 0x1f8b local Spinner = class() function Spinner:init(args) local defaults = { - timeout = .095, + timeout = .075, c = os.clock(), spinIndex = 0, spinSymbols = { '-', '/', '|', '\\' } diff --git a/core/t.lua b/core/t.lua index 49f2aa1..aef9b51 100644 --- a/core/t.lua +++ b/core/t.lua @@ -1,4 +1,6 @@ -function doCommand(command, moves) +local turtle = _G.turtle + +local function doCommand(command, moves) local function format(value) if type(value) == 'boolean' then @@ -49,6 +51,8 @@ function doCommand(command, moves) [ 'r' ] = turtle.turnRight, [ 'l' ] = turtle.turnLeft, [ 'ta' ] = turtle.turnAround, + [ 'el' ] = turtle.equipLeft, + [ 'er' ] = turtle.equipRight, [ 'DD' ] = turtle.digDown, [ 'DU' ] = turtle.digUp, [ 'D' ] = turtle.dig, @@ -64,7 +68,7 @@ function doCommand(command, moves) if cmds[command] then runCommand(cmds[command], moves) elseif repCmds[command] then - for i = 1, moves do + for _ = 1, moves do if not runCommand(repCmds[command]) then break end @@ -79,7 +83,7 @@ if #args > 0 then else print('Enter command (q to quit):') while true do - local cmd = read() + local cmd = _G.read() if cmd == 'q' then break end args = { } diff --git a/milo/MiloRemote.lua b/milo/MiloRemote.lua index 8c06513..358a6e2 100644 --- a/milo/MiloRemote.lua +++ b/milo/MiloRemote.lua @@ -21,7 +21,7 @@ local depositMode = { [ false ] = { text = '\215', textColor = colors.red, help = 'Deposit disabled' }, } -local displayMode = { +local displayModes = { [0] = { text = 'A', help = 'Showing all items' }, [1] = { text = 'I', help = 'Showing inventory items' }, [2] = { text = 'C', help = 'Showing craftable items' }, @@ -98,8 +98,8 @@ local page = UI.Page { display = UI.Button { x = -3, event = 'toggle_display', - text = displayMode[config.displayMode].text, - help = displayMode[config.displayMode].help, + text = displayModes[config.displayMode].text, + help = displayModes[config.displayMode].help, }, }, accelerators = { @@ -357,7 +357,7 @@ function page:eventHandler(event) elseif event.type == 'toggle_display' then config.displayMode = (config.displayMode + 1) % 3 - Util.merge(event.button, displayMode[config.displayMode]) + Util.merge(event.button, displayModes[config.displayMode]) event.button:draw() self:applyFilter() self:setStatus(event.button.help) diff --git a/milo/apis/storage.lua b/milo/apis/storage.lua index 2fdc35a..32fc095 100644 --- a/milo/apis/storage.lua +++ b/milo/apis/storage.lua @@ -164,7 +164,6 @@ function Storage:listItems(throttle) return self.cache end --- TODO: is there any reason now to maintain 2 lists local cache = { } throttle = throttle or Util.throttle() diff --git a/milo/apis/turtle/craft.lua b/milo/apis/turtle/craft.lua index ccb419c..94dfdd3 100644 --- a/milo/apis/turtle/craft.lua +++ b/milo/apis/turtle/craft.lua @@ -126,7 +126,6 @@ local function turtleCraft(recipe, storage, request, count) for k,v in pairs(recipe.ingredients) do local item = splitKey(v) if storage:export(storage.localName, k, count, item) ~= count then - -- TODO: FIX: ingredients cannot be stacked request.status = 'unknown error' request.statusCode = Craft.STATUS_ERROR return diff --git a/milo/core/machines.lua b/milo/core/machines.lua index 60ccc12..c353382 100644 --- a/milo/core/machines.lua +++ b/milo/core/machines.lua @@ -438,14 +438,13 @@ function nodeWizard:enable(node) self.node.adapter = adapter node.adapter = adapter -_G._p2 = self.node +_G._p3 = self.node local choices = { { name = 'Ignore', value = 'ignore' }, } for _, page in pairs(self.wizard.pages) do if page.isValidType then - -- TODO: dedupe list local choice = page:isValidType(self.node) if choice and not Util.find(choices, 'value', choice.value) then table.insert(choices, choice) @@ -474,6 +473,10 @@ function nodeWizard:eventHandler(event) UI:setPreviousPage() elseif event.type == 'accept' then + + local adapter = self.node.adapter + self.node.adapter = nil + Util.prune(self.node, function(v) if type(v) == 'boolean' then return v @@ -487,13 +490,15 @@ function nodeWizard:eventHandler(event) Util.clear(context.config.nodes[self.node.name]) Util.merge(context.config.nodes[self.node.name], self.node) + context.config.nodes[self.node.name].adapter = adapter + saveConfig() UI:setPreviousPage() elseif event.type == 'choice_change' then local help - if event.choice and event.choice.help then -- TODO: new param sent by UI api + if event.choice and event.choice.help then help = event.choice.help else help = '' diff --git a/milo/plugins/activityView.lua b/milo/plugins/activityView.lua index 67fd7f0..7af2b03 100644 --- a/milo/plugins/activityView.lua +++ b/milo/plugins/activityView.lua @@ -7,15 +7,12 @@ local Util = require('util') local colors = _G.colors local context = Milo:getContext() local device = _G.device -local monitor = context.storage:getSingleNode('activity') --[[ Configuration Page ]]-- local template = [[%sDisplays the amount of items entering or leaving storage.%s -Right-clicking on the activity monitor will reset the totals. - -%sMilo must be restarted to activate diplay.]] +Right-clicking on the activity monitor will reset the totals.]] local activityWizardPage = UI.Window { title = 'Activity Monitor', @@ -24,7 +21,7 @@ local activityWizardPage = UI.Window { [1] = UI.TextArea { x = 2, ex = -2, y = 2, ey = -2, marginRight = 0, - value = string.format(template, Ansi.yellow, Ansi.reset, Ansi.orange), + value = string.format(template, Ansi.yellow, Ansi.reset), }, } @@ -43,122 +40,128 @@ end UI:getPage('nodeWizard').wizard:add({ activity = activityWizardPage }) -if not monitor then - return -end - -local page = UI.Window { - parent = UI.Device { - device = monitor.adapter, - textScale = .5, - }, - grid = UI.Grid { - columns = { - { heading = 'Qty', key = 'count', width = 6 }, - { heading = 'Change', key = 'change', width = 6 }, - { heading = 'Rate', key = 'rate', width = 6 }, - { heading = 'Name', key = 'displayName' }, +--[[ Display ]]-- +local function createPage(node) + local page = UI.Window { + parent = UI.Device { + device = node.adapter, + textScale = .5, }, - sortColumn = 'displayName', - }, -} + grid = UI.Grid { + columns = { + { heading = 'Qty', key = 'count', width = 6 }, + { heading = 'Change', key = 'change', width = 6 }, + { heading = 'Rate', key = 'rate', width = 6 }, + { heading = 'Name', key = 'displayName' }, + }, + sortColumn = 'displayName', + }, + } -function page.grid:getRowTextColor(row, selected) - if row.lastCount and row.lastCount ~= row.count then - return row.count > row.lastCount and colors.yellow or colors.lightGray - end - return UI.Grid:getRowTextColor(row, selected) -end - -function page.grid:getDisplayValues(row) - row = Util.shallowCopy(row) - - local ind = '+' - if row.change < 0 then - ind = '' - end - - row.change = ind .. Util.toBytes(row.change) - row.count = Util.toBytes(row.count) - row.rate = Util.toBytes(row.rate) - - return row -end - -function page:reset() - self.lastItems = nil - self.grid:setValues({ }) - self.grid:clear() - self.grid:draw() -end - -function page:refresh() - local t = context.storage.cache - - if not self.lastItems then - self.lastItems = { } - for k,v in pairs(t) do - self.lastItems[k] = { - displayName = v.displayName, - initialCount = v.count, - } + function page.grid:getRowTextColor(row, selected) + if row.lastCount and row.lastCount ~= row.count then + return row.count > row.lastCount and colors.yellow or colors.lightGray end - self.timestamp = os.clock() + return UI.Grid:getRowTextColor(row, selected) + end + + function page.grid:getDisplayValues(row) + row = Util.shallowCopy(row) + + local ind = '+' + if row.change < 0 then + ind = '' + end + + row.change = ind .. Util.toBytes(row.change) + row.count = Util.toBytes(row.count) + row.rate = Util.toBytes(row.rate) + + return row + end + + function page:reset() + self.lastItems = nil self.grid:setValues({ }) + self.grid:clear() + self.grid:draw() + end - else - for _,v in pairs(self.lastItems) do - v.lastCount = v.count - v.count = nil - end + function page:refresh() + local t = context.storage.cache - self.elapsed = os.clock() - self.timestamp - - for k,v in pairs(t) do - local v2 = self.lastItems[k] - if v2 then - v2.count = v.count - else + if not self.lastItems then + self.lastItems = { } + for k,v in pairs(t) do self.lastItems[k] = { displayName = v.displayName, - count = v.count, - initialCount = 0, + initialCount = v.count, } end - end + self.timestamp = os.clock() + self.grid:setValues({ }) - local changedItems = { } - for k,v in pairs(self.lastItems) do - if not v.count then - v.count = 0 + else + for _,v in pairs(self.lastItems) do + v.lastCount = v.count + v.count = nil end - if v.count ~= v.initialCount then - v.change = v.count - v.initialCount - v.rate = Util.round(60 / self.elapsed * v.change, 1) - changedItems[k] = v - end - end - self.grid:setValues(changedItems) + self.elapsed = os.clock() - self.timestamp + + for k,v in pairs(t) do + local v2 = self.lastItems[k] + if v2 then + v2.count = v.count + else + self.lastItems[k] = { + displayName = v.displayName, + count = v.count, + initialCount = 0, + } + end + end + + local changedItems = { } + for k,v in pairs(self.lastItems) do + if not v.count then + v.count = 0 + end + if v.count ~= v.initialCount then + v.change = v.count - v.initialCount + v.rate = Util.round(60 / self.elapsed * v.change, 1) + changedItems[k] = v + end + end + + self.grid:setValues(changedItems) + end + self.grid:draw() end - self.grid:draw() -end -function page:update() - page:refresh() - page:sync() -end - -Event.on('monitor_touch', function(_, side) - if side == monitor.adapter.side then - page:reset() + function page:update() + page:refresh() page:sync() end -end) -page:enable() -page:draw() -page:sync() + page:enable() + page:draw() + page:sync() + + return page +end + +local pages = { } + +Event.on('monitor_touch', function(_, side) + local function filter(node) + return node.adapter.name == side and pages[node.name] + end + for node in context.storage:filterActive('activity', filter) do + pages[node.name]:reset() + pages[node.name]:sync() + end +end) --[[ Task ]]-- local ActivityTask = { @@ -167,7 +170,12 @@ local ActivityTask = { } function ActivityTask:cycle() - page:update() + for node in context.storage:filterActive('activity') do + if not pages[node.name] then + pages[node.name] = createPage(node) + end + pages[node.name]:update() + end end Milo:registerTask(ActivityTask) diff --git a/milo/plugins/item.lua b/milo/plugins/item.lua index 052d2d0..24430b5 100644 --- a/milo/plugins/item.lua +++ b/milo/plugins/item.lua @@ -110,10 +110,10 @@ local itemPage = UI.Page { backgroundColor = colors.cyan, titleBar = UI.TitleBar { title = 'Select Machine', - previousPage = true, + event = 'cancel_machine', }, grid = UI.ScrollingGrid { - y = 2, ey = -4, + y = 2, ey = -5, disableHeader = true, values = context.config.nodes, columns = { @@ -122,13 +122,14 @@ local itemPage = UI.Page { sortColumn = 'displayName', }, button1 = UI.Button { - x = -14, y = -2, + x = -14, y = -3, text = 'Ok', event = 'set_machine', }, button2 = UI.Button { - x = -9, y = -2, + x = -9, y = -3, text = 'Cancel', event = 'cancel_machine', }, + statusBar = UI.StatusBar { values = 'Enter or double click to select' }, }, info = UI.SlideOut { titleBar = UI.TitleBar { @@ -155,6 +156,8 @@ function itemPage:enable(item) self.form:setValues(self.res) self.titleBar.title = item.displayName or item.name + self.form[6].inactive = not Craft.machineLookup[self.item.key] + UI.Page.enable(self) self:focusFirst() end @@ -169,6 +172,13 @@ function itemPage.machines.grid:getDisplayValues(row) return row end + function itemPage.machines.grid:getRowTextColor(row, selected) + if row.name == Craft.machineLookup[itemPage.item.key] then + return colors.yellow + end + return UI.Grid:getRowTextColor(row, selected) + end + function itemPage.rsControl:enable() local devices = self.form[1].choices Util.clear(devices) @@ -227,8 +237,15 @@ function itemPage:eventHandler(event) UI:setPreviousPage() + elseif event.type == 'grid_select' then + Craft.machineLookup[self.item.key] = event.selected.name + self.machines.grid:draw() + elseif event.type == 'set_machine' then - --TODO save machine + local machine = self.machines.grid:getSelected() + if machine then + Util.writeTable(Craft.MACHINE_LOOKUP, Craft.machineLookup) + end self.machines:hide() elseif event.type == 'cancel_machine' then diff --git a/milo/plugins/jobMonitor.lua b/milo/plugins/jobMonitor.lua index 00d40b8..eb750d0 100644 --- a/milo/plugins/jobMonitor.lua +++ b/milo/plugins/jobMonitor.lua @@ -1,4 +1,3 @@ -local Ansi = require('ansi') local Craft = require('turtle.craft') local Event = require('event') local itemDB = require('itemDB') @@ -9,14 +8,8 @@ local Util = require('util') local colors = _G.colors local context = Milo:getContext() local device = _G.device -local monitor = context.storage:getSingleNode('jobs') --[[ Configuration Screen ]] -local template = -[[%sDisplays the crafting progress%s - -%sMilo must be restarted to activate diplay.]] - local wizardPage = UI.Window { title = 'Crafting Monitor', index = 2, @@ -24,7 +17,8 @@ local wizardPage = UI.Window { [1] = UI.TextArea { x = 2, ex = -2, y = 2, ey = -2, marginRight = 0, - value = string.format(template, Ansi.yellow, Ansi.reset, Ansi.orange), + textColor = colors.yellow, + value = 'Displays the crafting progress.' }, } @@ -44,105 +38,115 @@ end UI:getPage('nodeWizard').wizard:add({ jobs = wizardPage }) --[[ Display ]] -if not monitor then - return -end - -- TODO: some way to cancel a job - -local jobMonitor = UI.Page { - parent = UI.Device { - device = monitor.adapter, - textScale = .5, - }, - grid = UI.Grid { - sortColumn = 'index', - backgroundFocusColor = colors.black, - columns = { - { heading = 'Qty', key = 'remaining', width = 4 }, - { heading = 'Crafting', key = 'displayName', }, - { heading = 'Status', key = 'status', }, - { heading = 'need', key = 'need', width = 4 }, --- { heading = 'total', key = 'total', width = 4 }, --- { heading = 'used', key = 'used', width = 4 }, --- { heading = 'count', key = 'count', width = 4 }, - { heading = 'crafted', key = 'crafted', width = 5 }, --- { heading = 'Progress', key = 'progress', width = 8 }, +local function createPage(node) + local page = UI.Page { + parent = UI.Device { + device = node.adapter, + textScale = .5, }, - }, -} + grid = UI.Grid { + sortColumn = 'index', + backgroundFocusColor = colors.black, + columns = { + { heading = 'Qty', key = 'remaining', width = 4 }, + { heading = 'Crafting', key = 'displayName', }, + { heading = 'Status', key = 'status', }, + { heading = 'need', key = 'need', width = 4 }, + -- { heading = 'total', key = 'total', width = 4 }, + -- { heading = 'used', key = 'used', width = 4 }, + -- { heading = 'count', key = 'count', width = 4 }, + { heading = 'crafted', key = 'crafted', width = 5 }, + -- { heading = 'Progress', key = 'progress', width = 8 }, + }, + }, + } -function jobMonitor:updateList(craftList) - if not Milo:isCraftingPaused() then - local t = { } - for _,v in pairs(craftList) do - table.insert(t, v) - v.index = #t - for k2,v2 in pairs(v.ingredients or { }) do - if v2.key ~= v.key --[[and v2.statusCode ]] then - table.insert(t, v2) - if not v2.displayName then - v2.displayName = itemDB:getName(k2) + function page:updateList(craftList) + if not Milo:isCraftingPaused() then + local t = { } + for _,v in pairs(craftList) do + table.insert(t, v) + v.index = #t + for k2,v2 in pairs(v.ingredients or { }) do + if v2.key ~= v.key --[[and v2.statusCode ]] then + table.insert(t, v2) + if not v2.displayName then + v2.displayName = itemDB:getName(k2) + end + v2.index = #t end - v2.index = #t end end + self.grid:setValues(t) + self.grid:update() + self:draw() + self:sync() end - self.grid:setValues(t) - self.grid:update() - self:draw() - self:sync() end + + function page.grid:getDisplayValues(row) + row = Util.shallowCopy(row) + if not row.displayName then + row.displayName = itemDB:getName(row) + end + if row.requested then + row.remaining = math.max(0, row.requested - row.crafted) + else + row.displayName = ' ' .. row.displayName + end + --row.progress = string.format('%d/%d', row.crafted, row.count) + return row + end + + function page.grid:getRowTextColor(row, selected) + local statusColor = { + [ Craft.STATUS_ERROR ] = colors.red, + [ Craft.STATUS_WARNING ] = colors.orange, + [ Craft.STATUS_INFO ] = colors.yellow, + [ Craft.STATUS_SUCCESS ] = colors.green, + } + return row.statusCode and statusColor[row.statusCode] or + UI.Grid:getRowTextColor(row, selected) + end + + page:enable() + page:draw() + page:sync() + + return page end -function jobMonitor.grid:getDisplayValues(row) - row = Util.shallowCopy(row) - if not row.displayName then - row.displayName = itemDB:getName(row) - end - if row.requested then - row.remaining = math.max(0, row.requested - row.crafted) - else - row.displayName = ' ' .. row.displayName - end - --row.progress = string.format('%d/%d', row.crafted, row.count) - return row -end - -function jobMonitor.grid:getRowTextColor(row, selected) - local statusColor = { - [ Craft.STATUS_ERROR ] = colors.red, - [ Craft.STATUS_WARNING ] = colors.orange, - [ Craft.STATUS_INFO ] = colors.yellow, - [ Craft.STATUS_SUCCESS ] = colors.green, - } - return row.statusCode and statusColor[row.statusCode] or - UI.Grid:getRowTextColor(row, selected) -end +local pages = { } Event.on({ 'milo_resume', 'milo_pause' }, function(_, reason) - if reason then - jobMonitor.grid:clear() - jobMonitor.grid:centeredWrite(math.ceil(jobMonitor.grid.height / 2), reason.msg) - else - jobMonitor.grid:draw() + for node in context.storage:filterActive('jobs') do + local page = pages[node.name] + if page then + if reason then + page.grid:clear() + page.grid:centeredWrite(math.ceil(page.grid.height / 2), reason.msg) + else + page.grid:draw() + end + page:sync() + end end - jobMonitor:sync() end) -jobMonitor:enable() -jobMonitor:draw() -jobMonitor:sync() - --[[ Task ]] -local jobMonitorTask = { +local task = { name = 'job status', priority = 80, } -function jobMonitorTask:cycle() - jobMonitor:updateList(context.craftingQueue) +function task:cycle() + for node in context.storage:filterActive('jobs') do + if not pages[node.name] then + pages[node.name] = createPage(node) + end + pages[node.name]:updateList(context.craftingQueue) + end end -Milo:registerTask(jobMonitorTask) -context.jobMonitor = jobMonitor +Milo:registerTask(task) diff --git a/milo/plugins/listing.lua b/milo/plugins/listing.lua index 5bd911d..bd554b7 100644 --- a/milo/plugins/listing.lua +++ b/milo/plugins/listing.lua @@ -5,10 +5,17 @@ local Milo = require('milo') local UI = require('ui') local Util = require('util') -local colors = _G.colors -local context = Milo:getContext() +local colors = _G.colors +local context = Milo:getContext() +local displayMode = Milo:getState('displayMode') or 0 -local function filterItems(t, filter, displayMode) +local displayModes = { + [0] = { text = 'A', help = 'Showing all items' }, + [1] = { text = 'I', help = 'Showing inventory items' }, + [2] = { text = 'C', help = 'Showing craftable items' }, +} + +local function filterItems(t, filter) if filter or displayMode > 0 then local r = { } if filter then @@ -96,7 +103,8 @@ local listingPage = UI.Page { x = -3, event = 'toggle_display', value = 0, - text = 'A', + text = displayModes[displayMode].text, + help = displayModes[displayMode].help, }, }, notification = UI.Notification(), @@ -112,7 +120,6 @@ local listingPage = UI.Page { q = 'quit', }, - displayMode = 0, } function listingPage.statusBar:draw() @@ -197,18 +204,12 @@ function listingPage:eventHandler(event) self:setFocus(self.statusBar.filter) elseif event.type == 'toggle_display' then - local values = { - [0] = 'A', - [1] = 'I', - [2] = 'C', - } - - event.button.value = (event.button.value + 1) % 3 - self.displayMode = event.button.value - event.button.text = values[event.button.value] + displayMode = (displayMode + 1) % 3 + Util.merge(event.button, displayModes[displayMode]) event.button:draw() self:applyFilter() self.grid:draw() + Milo:setState('displayMode', displayMode) elseif event.type == 'learn' then UI:setPage('learn') @@ -275,7 +276,7 @@ function listingPage:refresh(force) end function listingPage:applyFilter() - local t = filterItems(self.allItems, self.filter, self.displayMode) + local t = filterItems(self.allItems, self.filter) self.grid:setValues(t) end