From 1eaaca2cc347e76b4314e9e449309b7b4b459781 Mon Sep 17 00:00:00 2001 From: kepler155c Date: Mon, 12 Nov 2018 20:22:14 -0500 Subject: [PATCH] milo better user experience --- core/apis/itemDB.lua | 1 + farms/farmer.lua | 2 +- milo/MiloRemote.lua | 154 +++++++++++++++++++----------- milo/autorun/milo.lua | 8 ++ milo/core/machines.lua | 28 ++++-- milo/etc/apps/apps.db | 13 +++ milo/plugins/activityView.lua | 6 +- milo/plugins/brewingStandView.lua | 6 +- milo/plugins/exportView.lua | 9 +- milo/plugins/importView.lua | 9 +- milo/plugins/inputChestView.lua | 6 +- milo/plugins/jobMonitor.lua | 6 +- milo/plugins/listing.lua | 16 ++-- milo/plugins/manipulatorView.lua | 6 +- milo/plugins/potionImportTask.lua | 2 +- milo/plugins/storageView.lua | 8 +- milo/plugins/trashcanView.lua | 6 +- 17 files changed, 204 insertions(+), 82 deletions(-) create mode 100644 milo/autorun/milo.lua create mode 100644 milo/etc/apps/apps.db diff --git a/core/apis/itemDB.lua b/core/apis/itemDB.lua index 95bd135..ab014e9 100644 --- a/core/apis/itemDB.lua +++ b/core/apis/itemDB.lua @@ -31,6 +31,7 @@ local function safeString(text) end function itemDB:makeKey(item) + if not item then error('itemDB:makeKey: item is required', 2) end return table.concat({ item.name, item.damage or '*', item.nbtHash }, ':') end diff --git a/farms/farmer.lua b/farms/farmer.lua index ac182f8..877d1a0 100644 --- a/farms/farmer.lua +++ b/farms/farmer.lua @@ -139,7 +139,7 @@ local function harvest(blocks) elseif b.action == 'bump' then if turtle.faceAgainst(b) then turtle.equip('right', 'plethora:module:3') - os.sleep(.3) + os.sleep(.5) -- search the ground for the dropped cactus local sensed = peripheral.call('right', 'sense') turtle.equip('right', 'minecraft:diamond_pickaxe') diff --git a/milo/MiloRemote.lua b/milo/MiloRemote.lua index fa16b57..2ae9ffa 100644 --- a/milo/MiloRemote.lua +++ b/milo/MiloRemote.lua @@ -1,5 +1,6 @@ _G.requireInjector(_ENV) +local Config = require('config') local Event = require('event') local Socket = require('socket') local sync = require('sync').sync @@ -13,48 +14,26 @@ local socket local SHIELD_SLOT = 2 -local options = { - user = { arg = 'u', type = 'string', - desc = 'User name associated with bound manipulator' }, - slot = { arg = 's', type = 'number', - desc = 'Optional inventory slot to use to transfer to milo' }, - shield = { arg = 'e', type = 'flag', - desc = 'Use shield slot to use to transfer to milo' }, - server = { arg = 'm', type = 'number', - desc = 'ID of Milo server' }, - help = { arg = 'h', type = 'flag', value = false, - desc = 'Displays the options' }, -} - -local args = { ... } -if not Util.getOptions(options, args) then - print() - error('Invalid arguments') -end - -if not options.user.value or not options.server.value then - Util.showOptions(options) - print() - error('Invalid arguments') -end - -if (options.slot.value or options.shield.value) and - not (device.neuralInterface and device.neuralInterface.getInventory) then - error('Introspection module is required for transferring items') -end +local config = Config.load('miloRemote', { }) local page = UI.Page { dummy = UI.Window { - x = 1, ex = -10, y = 1, height = 1, + x = 1, ex = -13, y = 1, height = 1, infoBar = UI.StatusBar { backgroundColor = colors.lightGray, }, }, refresh = UI.Button { - y = 1, x = -9, + y = 1, x = -12, event = 'refresh', text = 'Refresh', }, + setupButton = UI.Button { + y = 1, x = -3, + event = 'setup', + text = '\206', + help = 'Configuration', + }, grid = UI.Grid { y = 2, ey = -2, columns = { @@ -106,6 +85,46 @@ local page = UI.Page { q = 'quit', }, + setup = UI.SlideOut { + backgroundColor = colors.cyan, + titleBar = UI.TitleBar { + title = 'Remote Setup', + }, + form = UI.Form { + x = 2, ex = -2, y = 2, ey = -1, + values = config, + [1] = UI.TextEntry { + formLabel = 'Server', formKey = 'server', + help = 'ID for the server', + shadowText = 'Milo server ID', + limit = 6, + validate = 'numeric', + required = true, + }, + [2] = UI.TextEntry { + formLabel = 'User Name', formKey = 'user', + help = 'User name for bound manipulator', + shadowText = 'User name', + limit = 50, + required = true, + }, + [3] = UI.TextEntry { + formLabel = 'Return Slot', formKey = 'slot', + help = 'Use a slot for sending to storage', + shadowText = 'Inventory slot #', + limit = 5, + validate = 'numeric', + required = true, + }, + [4] = UI.Checkbox { + formLabel = 'Shield Slot', formKey = 'useShield', + help = 'or use the shield slot for sending' + }, + }, + statusBar = UI.StatusBar { + backgroundColor = colors.cyan, + }, + }, displayMode = 0, items = { }, } @@ -139,14 +158,22 @@ end function page:sendRequest(data) local response + if not config.server then + self:setStatus('Invalid configuration') + Event.onTimeout(2, function() + self:setStatus('') + end) + return + end + sync(self, function() local msg for _ = 1, 2 do if not socket or not socket.connected then self:setStatus('connecting ...') - socket, msg = Socket.connect(options.server.value, 4242) + socket, msg = Socket.connect(config.server, 4242) if socket then - socket:write(options.user.value) + socket:write(config.user) local r = socket:read(2) if r and not r.msg then self:setStatus('connected ...') @@ -203,7 +230,6 @@ end function page:transfer(item, count) local response = self:sendRequest({ request = 'transfer', item = item, count = count }) if response then - _debug(response) item.count = response.current - response.count self.grid:draw() if response.craft > 0 then @@ -214,10 +240,29 @@ function page:transfer(item, count) end end +function page.setup:eventHandler(event) + if event.type == 'focus_change' then + self.statusBar:setStatus(event.focused.help) + end + return UI.SlideOut.eventHandler(self, event) +end + function page:eventHandler(event) if event.type == 'quit' then UI:exitPullEvents() + elseif event.type == 'setup' then + self.setup:show() + + elseif event.type == 'form_complete' then + Config.update('miloRemote', config) + self.setup:hide() + self:refresh() + self.grid:draw() + + elseif event.type == 'form_cancel' then + self.setup:hide() + elseif event.type == 'focus_change' then self.dummy.infoBar:setStatus(event.focused.help) @@ -290,6 +335,9 @@ end function page:enable() self:setFocus(self.statusBar.filter) UI.Page.enable(self) + if not config.server then + self.setup:show() + end Event.onTimeout(.1, function() self:refresh() self.grid:draw() @@ -311,31 +359,21 @@ function page:applyFilter() self.grid:setValues(t) end -if options.slot.value or options.shield.value then - local inv = 'getInventory' - local slotNo = options.slot.value - local slotValue = options.slot.value - - if options.shield.value then - slotNo = SHIELD_SLOT - slotValue = 'shield' - inv = 'getEquipment' - end - - Event.addRoutine(function() - while true do - os.sleep(1.5) - local neural = device.neuralInterface - if not neural or not neural[inv] then - _G._debug('missing Introspection module') - end - - local method = neural and neural[inv] - local item = method and method().getItemMeta(slotNo) +Event.addRoutine(function() + while true do + os.sleep(1.5) + local neural = device.neuralInterface + local inv = config.useShield and 'getEquipment' or 'getInventory' + if not neural or not neural[inv] then + _G._debug('missing Introspection module') + elseif config.server then + local method = neural[inv] + local item = method and method().getItemMeta(config.useShield and SHIELD_SLOT or config.slot) if item then + local slotNo = config.useShield and 'shield' or config.slot local response = page:sendRequest({ request = 'deposit', - slot = slotValue, + slot = slotNo, count = item.count, key = table.concat({ item.name, item.damage, item.nbtHash }, ':') }) @@ -349,8 +387,8 @@ if options.slot.value or options.shield.value then end end end - end) -end + end +end) UI:setPage(page) UI:pullEvents() diff --git a/milo/autorun/milo.lua b/milo/autorun/milo.lua new file mode 100644 index 0000000..3304f36 --- /dev/null +++ b/milo/autorun/milo.lua @@ -0,0 +1,8 @@ +local device = _G.device +local shell = _ENV.shell + +if device.workbench then + shell.openForegroundTab('Milo') +elseif device.neuralInterface then + shell.openForegroundTab('MiloRemote') +end diff --git a/milo/core/machines.lua b/milo/core/machines.lua index 388a651..75b594d 100644 --- a/milo/core/machines.lua +++ b/milo/core/machines.lua @@ -62,6 +62,9 @@ local networkPage = UI.Page { backgroundColor = colors.lightGray, }, notification = UI.Notification { }, + accelerators = { + delete = 'remove_node', + } } function networkPage.grid:getDisplayValues(row) @@ -236,7 +239,9 @@ The settings will take effect immediately!]], { heading = 'Name', key = 'displayName' }, }, sortColumn = 'displayName', - help = 'Select item to export', + accelerators = { + delete = 'remove_entry', + }, }, remove = UI.Button { x = -4, y = 4, @@ -255,7 +260,7 @@ The settings will take effect immediately!]], { name = 'Yes', value = true }, { name = 'No', value = false }, }, - help = 'Ignore damage of item when exporting' + help = 'Ignore damage of item' }, [2] = UI.Chooser { width = 7, @@ -266,7 +271,7 @@ The settings will take effect immediately!]], { name = 'Yes', value = true }, { name = 'No', value = false }, }, - help = 'Ignore NBT of item when exporting' + help = 'Ignore NBT of item' }, [3] = UI.Chooser { width = 13, @@ -276,7 +281,7 @@ The settings will take effect immediately!]], { name = 'whitelist', value = false }, { name = 'blacklist', value = true }, }, - help = 'Ignore damage of item when exporting' + help = 'Ignore damage of item' }, scan = UI.Button { x = -11, y = 1, @@ -377,7 +382,7 @@ function nodeWizard.wizard.pages.general:enable() self:focusFirst() end -function nodeWizard.wizard.pages.general:setNode(node) +function nodeWizard.wizard.pages.general:showInventory(node) local inventory if device[node.name] and device[node.name].list then @@ -437,7 +442,7 @@ _G._p2 = self.node if page.isValidType then -- TODO: dedupe list local choice = page:isValidType(self.node) - if choice then + if choice and not Util.find(choices, 'value', choice.value) then table.insert(choices, choice) end end @@ -446,6 +451,8 @@ _G._p2 = self.node self.wizard.pages.general.form[2].choices = choices self.wizard.pages.general.form:setValues(self.node) + self.wizard.pages.general:showInventory(self.node) + -- restore indices for _, page in pairs(self.wizard.pages) do if not page.oindex then @@ -479,6 +486,15 @@ function nodeWizard:eventHandler(event) 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 + help = event.choice.help + else + help = '' + end + self.statusBar:setStatus(help) + elseif event.type == 'edit_filter' then self.filter:show(event.entry, event.callback, event.whitelistOnly) diff --git a/milo/etc/apps/apps.db b/milo/etc/apps/apps.db new file mode 100644 index 0000000..76ad61f --- /dev/null +++ b/milo/etc/apps/apps.db @@ -0,0 +1,13 @@ +{ + [ "9302912a2d9794a47241faefc475335b4e07a581" ] = { + title = "Remote", + category = "Apps", + run = "MiloRemote", + }, + [ "eea426f9baef72a8fcefd091e0cec5ab94a76698" ] = { + title = "Milo", + category = "Apps", + run = "Milo", + requires = 'advancedTurtle', + }, +} diff --git a/milo/plugins/activityView.lua b/milo/plugins/activityView.lua index d313aa1..1a15748 100644 --- a/milo/plugins/activityView.lua +++ b/milo/plugins/activityView.lua @@ -30,7 +30,11 @@ local activityWizardPage = UI.Window { function activityWizardPage:isValidType(node) local m = device[node.name] - return m and m.type == 'monitor' and { name = 'Activity Monitor', value = 'activity' } + return m and m.type == 'monitor' and { + name = 'Activity Monitor', + value = 'activity', + help = 'Display storage activity' + } end function activityWizardPage:isValidFor(node) diff --git a/milo/plugins/brewingStandView.lua b/milo/plugins/brewingStandView.lua index 018a8c3..b3036a4 100644 --- a/milo/plugins/brewingStandView.lua +++ b/milo/plugins/brewingStandView.lua @@ -27,7 +27,11 @@ local brewingStandView = UI.Window { function brewingStandView:isValidType(node) local m = device[node.name] - return m and m.type == 'minecraft:brewing_stand'and { name = 'Brewing Stand', value = 'brewingStand' } + return m and m.type == 'minecraft:brewing_stand'and { + name = 'Brewing Stand', + value = 'brewingStand', + help = 'Auto-learning brewing stand', + } end function brewingStandView:isValidFor(node) diff --git a/milo/plugins/exportView.lua b/milo/plugins/exportView.lua index 201e8be..8bfcbf6 100644 --- a/milo/plugins/exportView.lua +++ b/milo/plugins/exportView.lua @@ -15,6 +15,9 @@ local exportView = UI.Window { }, sortColumn = 'slot', help = 'Edit this entry', + accelerators = { + delete = 'remove_entry', + }, }, text = UI.Text { x = 2, y = -2, @@ -38,7 +41,11 @@ local exportView = UI.Window { function exportView:isValidType(node) local m = device[node.name] - return m and m.pullItems and { name = 'Generic Inventory', value = 'machine' } + return m and m.pullItems and { + name = 'Generic Inventory', + value = 'machine', + help = 'Chest, furnace... (has an inventory)' + } end function exportView:isValidFor(node) diff --git a/milo/plugins/importView.lua b/milo/plugins/importView.lua index 996736c..cd3d6c3 100644 --- a/milo/plugins/importView.lua +++ b/milo/plugins/importView.lua @@ -15,6 +15,9 @@ local importView = UI.Window { }, sortColumn = 'slot', help = 'Edit this entry', + accelerators = { + delete = 'remove_entry', + }, }, text = UI.Text { x = 2, y = -2, @@ -38,7 +41,11 @@ local importView = UI.Window { function importView:isValidType(node) local m = device[node.name] - return m and m.pullItems and { name = 'Generic Inventory', value = 'machine' } + return m and m.pullItems and { + name = 'Generic Inventory', + value = 'machine', + help = 'Chest, furnace... (has an inventory)', + } end function importView:isValidFor(node) diff --git a/milo/plugins/inputChestView.lua b/milo/plugins/inputChestView.lua index 0177903..59d48fe 100644 --- a/milo/plugins/inputChestView.lua +++ b/milo/plugins/inputChestView.lua @@ -23,7 +23,11 @@ local inputChestWizardPage = UI.Window { function inputChestWizardPage:isValidType(node) local m = device[node.name] - return m and m.pullItems and { name = 'Input Chest', value = 'input' } + return m and m.pullItems and { + name = 'Input Chest', + value = 'input', + help = 'Sends all items to storage', + } end function inputChestWizardPage:isValidFor(node) diff --git a/milo/plugins/jobMonitor.lua b/milo/plugins/jobMonitor.lua index 30ee1f7..33d811a 100644 --- a/milo/plugins/jobMonitor.lua +++ b/milo/plugins/jobMonitor.lua @@ -29,7 +29,11 @@ local jobsWizardPage = UI.Window { function jobsWizardPage:isValidType(node) local m = device[node.name] - return m and m.type == 'monitor' and { name = 'Crafting Monitor', value = 'jobs' } + return m and m.type == 'monitor' and { + name = 'Crafting Monitor', + value = 'jobs', + help = 'Display crafting progress / jobs' + } end function jobsWizardPage:isValidFor(node) diff --git a/milo/plugins/listing.lua b/milo/plugins/listing.lua index def0050..aa5a557 100644 --- a/milo/plugins/listing.lua +++ b/milo/plugins/listing.lua @@ -36,8 +36,8 @@ local listingPage = UI.Page { --{ text = 'Forget', event = 'forget' }, { text = 'Craft', event = 'craft' }, { text = 'Edit', event = 'details' }, - { text = 'Network', event = 'network' }, - { text = 'Refresh', event = 'refresh', x = -9 }, + { text = 'Refresh', event = 'refresh', x = -12 }, + { text = '\206', event = 'network', x = -3 }, }, }, grid = UI.Grid { @@ -59,7 +59,7 @@ local listingPage = UI.Page { backgroundColor = colors.cyan, backgroundFocusColor = colors.cyan, accelerators = { - [ 'enter' ] = 'craft', + [ 'enter' ] = 'eject', }, }, storageStatus = UI.Text { @@ -198,10 +198,12 @@ function listingPage:eventHandler(event) elseif event.type == 'craft' then local item = self.grid:getSelected() - if Craft.findRecipe(item) or true then -- or item.is_craftable then - UI:setPage('craft', self.grid:getSelected()) - else - self.notification:error('No recipe defined') + if item then + if Craft.findRecipe(item) then -- or item.is_craftable then + UI:setPage('craft', self.grid:getSelected()) + else + self.notification:error('No recipe defined') + end end elseif event.type == 'text_change' and event.element == self.statusBar.filter then diff --git a/milo/plugins/manipulatorView.lua b/milo/plugins/manipulatorView.lua index 66ac15c..5c2feb4 100644 --- a/milo/plugins/manipulatorView.lua +++ b/milo/plugins/manipulatorView.lua @@ -35,7 +35,11 @@ function wizardPage:isValidType(node) return m and m.type == 'manipulator' and m.getEnder and - { name = 'Manipulator', value = 'manipulator' } + { + name = 'Manipulator', + value = 'manipulator', + help = 'Manipulator w/bound introspection mod' + } end function wizardPage:isValidFor(node) diff --git a/milo/plugins/potionImportTask.lua b/milo/plugins/potionImportTask.lua index 58a6a07..30aa793 100644 --- a/milo/plugins/potionImportTask.lua +++ b/milo/plugins/potionImportTask.lua @@ -12,7 +12,7 @@ local function filter(a) end function PotionImportTask:cycle(context) - for bs in context.storage:filterActive('machine', filter) do + for bs in context.storage:filterActive('brewingStand', filter) do if bs.adapter.getBrewTime() == 0 then local list = bs.adapter.list() diff --git a/milo/plugins/storageView.lua b/milo/plugins/storageView.lua index 70449b6..1ba333d 100644 --- a/milo/plugins/storageView.lua +++ b/milo/plugins/storageView.lua @@ -26,6 +26,7 @@ local storageView = UI.Window { x = 16, ex = -2, y = 3, value = '', }, +--[[ [4] = UI.Checkbox { formLabel = 'Void', formKey = 'voidExcess', help = 'Void excess if locked - TODO', @@ -36,6 +37,7 @@ local storageView = UI.Window { help = 'TODO', pruneEmpty = true, }, +]]-- }, } @@ -50,7 +52,11 @@ end function storageView:isValidType(node) local m = device[node.name] - return m and m.pullItems and { name = 'Storage', value = 'storage' } + return m and m.pullItems and { + name = 'Storage', + value = 'storage', + help = 'Use for item storage', + } end function storageView:isValidFor(node) diff --git a/milo/plugins/trashcanView.lua b/milo/plugins/trashcanView.lua index 2b5547e..e81969f 100644 --- a/milo/plugins/trashcanView.lua +++ b/milo/plugins/trashcanView.lua @@ -25,7 +25,11 @@ local trashcanWizardPage = UI.Window { function trashcanWizardPage:isValidType(node) local m = device[node.name] - return m and m.pullItems and { name = 'Trashcan', value = 'trashcan' } + return m and m.pullItems and { + name = 'Trashcan', + value = 'trashcan', + help = 'An inventory to send unwanted items', + } end function trashcanWizardPage:isValidFor(node)