From 9eff14f3ba9f945d54f86d54b523781ec3b4db92 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Wed, 6 May 2020 18:02:01 -0600 Subject: [PATCH 01/19] titlebar/close/moving of nwm windows --- common/debugMonitor.lua | 12 ++++++--- common/edit.lua | 3 --- lzwfs/system/lzwfs.lua | 1 - neural/apis/glasses.lua | 8 +++++- neural/fisher.lua | 2 +- neural/nwm.lua | 54 ++++++++++++++++++++++++++++++++++++++--- 6 files changed, 68 insertions(+), 12 deletions(-) diff --git a/common/debugMonitor.lua b/common/debugMonitor.lua index 74e8c84..d198f77 100644 --- a/common/debugMonitor.lua +++ b/common/debugMonitor.lua @@ -6,12 +6,16 @@ local peripheral = _G.peripheral local term = _G.term local args = { ... } -local mon = args[1] and device[args[1]] or peripheral.wrap(args[1]) or +local mon = not args[1] and term.current() or + device[args[1]] or + peripheral.wrap(args[1]) or peripheral.find('monitor') or error('Syntax: debug ') mon.clear() -mon.setTextScale(.5) +if mon.setTextScale then + mon.setTextScale(.5) +end mon.setCursorPos(1, 1) local oldDebug = _G._syslog @@ -26,7 +30,9 @@ repeat local e, side = os.pullEventRaw('monitor_touch') if e == 'monitor_touch' and side == mon.side then mon.clear() - mon.setTextScale(.5) + if mon.setTextScale then + mon.setTextScale(.5) + end mon.setCursorPos(1, 1) end until e == 'terminate' diff --git a/common/edit.lua b/common/edit.lua index f0c7be3..27784e1 100644 --- a/common/edit.lua +++ b/common/edit.lua @@ -202,7 +202,6 @@ local page = UI.Page { label = 'Find', search = UI.TextEntry { x = 7, ex = -3, - limit = 512, accelerators = { [ 'enter' ] = 'accept', }, @@ -232,7 +231,6 @@ local page = UI.Page { label = 'Save', filename = UI.TextEntry { x = 7, ex = -3, - limit = 512, accelerators = { [ 'enter' ] = 'accept', }, @@ -339,7 +337,6 @@ local page = UI.Page { quick_open = UI.SlideOut { filter_entry = UI.TextEntry { x = 2, y = 2, ex = -2, - limit = 256, shadowText = 'File name', accelerators = { [ 'enter' ] = 'accept', diff --git a/lzwfs/system/lzwfs.lua b/lzwfs/system/lzwfs.lua index 69bccee..5f898bd 100644 --- a/lzwfs/system/lzwfs.lua +++ b/lzwfs/system/lzwfs.lua @@ -29,7 +29,6 @@ local tab = UI.Tab { }, entry = UI.TextEntry { x = 3, y = 5 , ex = -3, - limit = 256, shadowText = 'enter new path', accelerators = { enter = 'add_path', diff --git a/neural/apis/glasses.lua b/neural/apis/glasses.lua index 1d8a1d4..1224883 100644 --- a/neural/apis/glasses.lua +++ b/neural/apis/glasses.lua @@ -5,7 +5,6 @@ local Terminal = require('opus.terminal') local Util = require('opus.util') -local colors = _G.colors local device = _G.device local Glasses = { } @@ -102,6 +101,13 @@ function Glasses.create(args) function gterm.getTextScale() return opts.scale end + function gterm.move(x, y) + if opts.x ~= x or opts.y ~= y then + opts.x, opts.y = x, y + pos = { x = opts.x * xs, y = opts.y * ys } + group.setPosition(pos.x, pos.y) + end + end gterm.name = opts.name gterm.side = opts.name diff --git a/neural/fisher.lua b/neural/fisher.lua index 88597af..d9c4c8a 100644 --- a/neural/fisher.lua +++ b/neural/fisher.lua @@ -47,7 +47,7 @@ local fsm = machine.create({ -- state changes onenterwait = function() - print('waitng for fishing rod to be selected') + print('waiting for fishing rod to be selected') if icon then icon.remove() icon = canvas.addItem({ w - 20, h - 20 }, 'minecraft:fishing_rod' ) diff --git a/neural/nwm.lua b/neural/nwm.lua index 7e54db0..91d2fe5 100644 --- a/neural/nwm.lua +++ b/neural/nwm.lua @@ -1,6 +1,9 @@ --[[ A simplistic window manager for glasses. - TODO: support moving windows via mouse drag. + + TODO: + opacity for text/background separately + support for specifying scale factor ]] local Config = require('opus.config') @@ -8,15 +11,17 @@ local Glasses = require('neural.glasses') local UI = require('opus.ui') local Util = require('opus.util') +local fs = _G.fs local kernel = _G.kernel local multishell = _ENV.multishell local shell = _ENV.shell local config = Config.load('nwm', { session = { } }) --- TODO: figure out how to better define scaling +-- TODO: figure out how to better support scaling local scale = .5 local xs, ys = 6 * scale, 9 * scale +local dragging local events = { glasses_click = 'mouse_click', @@ -31,16 +36,39 @@ local function hook(e, eventData) local y = math.floor(eventData[3] / ys) local clickedTab + if dragging then + if e == 'glasses_up' then + dragging = nil + elseif e == 'glasses_drag' then + local dx = x - dragging.ax + local dy = y - dragging.ay + dragging.tab.window.move(dragging.wx + dx, dragging.wy + dy) + dragging.tab.titleBar.move(dragging.wx + dx, dragging.wy + dy - 1) + + dragging.tab.wmargs.x = dragging.wx + dx + dragging.tab.wmargs.y = dragging.wy + dy + Config.update('nwm', config) + end + return + end + for _,tab in ipairs(kernel.routines) do if tab.window.type == 'glasses' then local wx, wy = tab.window.getPosition() local ww, wh = tab.window.getSize() - if x >= wx and x <= wx + ww and y >= wy and y <= wy + wh then + if x >= wx and x <= wx + ww and y > wy and y < wy + wh then clickedTab = tab x = x - wx y = y - wy break + elseif e == 'glasses_click' and x >= wx and x <= wx + ww and y == wy then + if x == wx + ww - 1 then + multishell.terminate(tab.uid) + else + dragging = { tab = tab, ax = x, ay = y, wx = wx, wy = wy } + end + return end end end @@ -65,6 +93,18 @@ kernel.hook(hookEvents, hook) local function run(args) local window = Glasses.create(args) + local titleBar = Glasses.create({ + x = args.x, + y = args.y - 1, + height = 1, + width = args.width, + opacity = args.opacity, + }) + titleBar.canvas:clear('yellow') + titleBar.canvas:write(1, 1, ' ' .. fs.getName(args.path), nil, 'black') + titleBar.canvas:write(args.width - 2, 1, ' x ', nil, 'black') + titleBar.redraw() + multishell.openTab({ path = args.path, args = args.args, @@ -73,8 +113,11 @@ local function run(args) Util.removeByValue(config.session, args) Config.update('nwm', config) window.destroy() + titleBar.destroy() end, window = window, + titleBar = titleBar, + wmargs = args, }) end @@ -90,6 +133,8 @@ UI:setPage(UI.Page { UI.Slider { min = 0, max = 255, formLabel = 'Opacity', formKey = 'opacity', formIndex = 3, + labelWidth = 3, + transform = math.floor, }, UI.Text { x = 10, y = 5, @@ -137,6 +182,9 @@ UI:setPage(UI.Page { run(opts) self.notification:success('Started program') end + + elseif event.type == 'form_cancel' then + UI:quit() end return UI.Page.eventHandler(self, event) end, -- 2.49.1 From 94b743bfc0a904bb9410b343c1108aed9864cb33 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Wed, 6 May 2020 18:49:28 -0600 Subject: [PATCH 02/19] remove border around windows in mwm --- monitor/mwm.lua | 131 ++++++++++++++++------------------------ neural/apis/glasses.lua | 5 +- 2 files changed, 56 insertions(+), 80 deletions(-) diff --git a/monitor/mwm.lua b/monitor/mwm.lua index eef8753..9eda98f 100644 --- a/monitor/mwm.lua +++ b/monitor/mwm.lua @@ -103,8 +103,8 @@ function Process:new(args) uid = nextUID(), x = args.x or 1, y = args.y or 1, - width = args.width + 2, - height = args.height + 3, + width = args.width, + height = args.height + 1, path = args.path, args = args.args or { }, title = args.title or 'shell', @@ -117,7 +117,7 @@ function Process:new(args) end self.container = Terminal.window(monitor, self.x, self.y, self.width, self.height, true) - self.window = window.create(self.container, 2, 3, args.width, args.height, true) + self.window = window.create(self.container, 1, 2, args.width, args.height, true) self.terminal = self.window self.container.setBackgroundColor(colors.black) @@ -153,62 +153,35 @@ function Process:new(args) return self end -function Process:focus(focused) - if focused then - self.container.setBackgroundColor(colors.yellow) - else - self.container.setBackgroundColor(colors.gray) - end - self.container.setTextColor(colors.black) - write(self.container, 2, 2, string.rep(' ', self.width - 2)) - write(self.container, 3, 2, self.title) - write(self.container, self.width - 2, 2, '*') +function Process:drawTitle(focused) + if self.showSizers and focused then + local sizers = '\25 \26 \24 \27' - if focused then - self.window.restoreCursor() - elseif self.showSizers then - self:drawSizers(false) + self.container.setBackgroundColor(colors.yellow) + self.container.setTextColor(colors.black) + + write(self.container, 1, 1, string.rep(' ', self.width)) + write(self.container, 2, 1, sizers) + + local str = string.format('%d x %d', self.width, self.height - 1) + write(self.container, 10, 1, str) + else + if focused then + self.container.setBackgroundColor(colors.yellow) + else + self.container.setBackgroundColor(colors.lightGray) + end + self.container.setTextColor(colors.black) + write(self.container, 1, 1, string.rep(' ', self.width)) + write(self.container, 2, 1, self.title) end + write(self.container, self.width - 1, 1, '*') end -function Process:drawSizers(showSizers) - local sizeChars = { - '\135', '\139', '\141', '\142' - } - - if Util.getVersion() < 1.8 then - sizeChars = { - '#', '#', '#', '#' - } - end - - self.showSizers = showSizers - - self.container.setBackgroundColor(colors.black) - self.container.setTextColor(colors.white) - - if self.showSizers then - write(self.container, 1, 1, sizeChars[1]) - write(self.container, self.width, 1, sizeChars[2]) - write(self.container, 1, self.height, sizeChars[3]) - write(self.container, self.width, self.height, sizeChars[4]) - - self.container.setTextColor(colors.yellow) - write(self.container, 1, 3, '+') - write(self.container, 1, 5, '-') - write(self.container, 3, 1, '+') - write(self.container, 5, 1, '-') - - local str = string.format('%d x %d', self.width - 2, self.height - 3) - write(self.container, (self.width - #str) / 2, 1, str) - - else - write(self.container, 1, 1, string.rep(' ', self.width)) - write(self.container, self.width, 1, ' ') - write(self.container, 1, self.height, ' ') - write(self.container, self.width, self.height, ' ') - write(self.container, 1, 3, ' ') - write(self.container, 1, 5, ' ') +function Process:focus(focused) + self:drawTitle(focused) + if focused then + self.window.restoreCursor() end end @@ -227,48 +200,48 @@ function Process:reposition() self.container.reposition(self.x, self.y, self.width, self.height) self.container.setBackgroundColor(colors.black) self.container.clear() - self.window.reposition(2, 3, self.width - 2, self.height - 3) + self.window.reposition(1, 2, self.width, self.height - 1) if self.window ~= self.terminal then - self.terminal.reposition(1, 1, self.width - 2, self.height - 3) + self.terminal.reposition(1, 1, self.width, self.height - 1) end redraw() end function Process:click(x, y) - if y == 2 then -- title bar - if x == self.width - 2 then + if y == 1 then -- title bar + if x == self.width - 1 then self:resume('terminate') + elseif not self.showSizers then + self.showSizers = not self.showSizers + self:drawTitle(true) else - self:drawSizers(not self.showSizers) + self:resizeClick(x, y) end - - elseif x == 1 or y == 1 then -- sizers - self:resizeClick(x, y) - elseif x > 1 and x < self.width then if self.showSizers then - self:drawSizers(false) + self.showSizers = false + self:drawTitle(true) end - self:resume('mouse_click', 1, x - 1, y - 2) - self:resume('mouse_up', 1, x - 1, y - 2) + self:resume('mouse_click', 1, x, y - 1) + self:resume('mouse_up', 1, x, y - 1) end end -function Process:resizeClick(x, y) - if x == 1 and y == 3 then +function Process:resizeClick(x) + if x == 2 then self.height = self.height + 1 - elseif x == 1 and y == 5 then + elseif x == 6 then self.height = self.height - 1 - elseif x == 3 and y == 1 then + elseif x == 4 then self.width = self.width + 1 - elseif x == 5 and y == 1 then + elseif x == 8 then self.width = self.width - 1 else return end self:reposition() self:resume('term_resize') - self:drawSizers(true) + self:drawTitle(true) multishell.saveSession(sessionFile) end @@ -393,8 +366,8 @@ function multishell.saveSession(filename) table.insert(t, { x = process.x, y = process.y, - width = process.width - 2, - height = process.height - 3, + width = process.width, + height = process.height - 1, path = process.path, args = process.args, }) @@ -446,7 +419,7 @@ function multishell.start() process.x = math.floor(x - (process.width) / 2) process.y = y process:reposition() - process:drawSizers(true) + process:drawTitle(true) multishell.saveSession(sessionFile) end end @@ -458,7 +431,7 @@ function multishell.start() if not focused.isShell then multishell.setFocus(1) -- shell is always 1 else - focused:resume(unpack(event)) + focused:resume(table.unpack(event)) end elseif event[1] == 'char' or @@ -468,12 +441,12 @@ function multishell.start() local focused = processes[#processes] if focused then - focused:resume(unpack(event)) + focused:resume(table.unpack(event)) end else for _,process in pairs(Util.shallowCopy(processes)) do - process:resume(unpack(event)) + process:resume(table.unpack(event)) end end diff --git a/neural/apis/glasses.lua b/neural/apis/glasses.lua index 1224883..be5fb86 100644 --- a/neural/apis/glasses.lua +++ b/neural/apis/glasses.lua @@ -1,5 +1,8 @@ --[[ Create a terminal compatible window for glasses canvas. + + Note that the extended chars on glasses are not consistent with + the normal cc font. ]] local Terminal = require('opus.terminal') @@ -47,9 +50,9 @@ function Glasses.create(args) map[k] = v + opts.opacity end - -- Position bottom left local pos = { x = opts.x * xs, y = opts.y * ys } + -- create an entry for every char as the glasses font is not fixed width :( local function init(group) for y = 1, opts.height do lines[y] = { -- 2.49.1 From 1fc2d08c18125d94e4dd89384e614c8e151f3c64 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Thu, 7 May 2020 17:15:30 -0600 Subject: [PATCH 03/19] some documentation and some bad icons --- neural/apis/glasses.lua | 50 ++++++++++++++++++++++----------------- neural/autorun/splash.lua | 36 +++++++++------------------- neural/etc/apps.db | 14 ++++++++++- neural/mobFollow.lua | 5 ++++ neural/neuralLook.lua | 5 ++++ neural/neuralRecorder.lua | 4 ++++ neural/nwm.lua | 6 ++--- 7 files changed, 69 insertions(+), 51 deletions(-) diff --git a/neural/apis/glasses.lua b/neural/apis/glasses.lua index be5fb86..1fb398c 100644 --- a/neural/apis/glasses.lua +++ b/neural/apis/glasses.lua @@ -8,26 +8,12 @@ local Terminal = require('opus.terminal') local Util = require('opus.util') -local device = _G.device +local device = _G.device local Glasses = { } -function Glasses.create(args) - local opts = { - x = 1, y = 20, - width = 51, height = 19, - scale = .5, - name = 'glasses', - opacity = 0xff, - } - Util.merge(opts, args) - - local xs, ys = 6 * opts.scale, 9 * opts.scale - local glasses = device['plethora:glasses'] - local canvas = glasses.canvas() - local _, cy = 1, 1 - local lines = { } - local map = { +function Glasses.getPalette(opacity) + local pal = { ['0'] = 0xF0F0F000, ['1'] = 0xF2B23300, ['2'] = 0xE57FD800, @@ -45,10 +31,30 @@ function Glasses.create(args) ['e'] = 0xCC4C4C00, ['f'] = 0x19191900, } - - for k,v in pairs(map) do - map[k] = v + opts.opacity + if opacity then + for k,v in pairs(pal) do + pal[k] = v + opacity + end end + return pal +end + +function Glasses.create(args) + local opts = { + x = 1, y = 20, + width = 51, height = 19, + scale = .5, + name = 'glasses', + opacity = 0xff, + } + Util.merge(opts, args) + + local xs, ys = 6 * opts.scale, 9 * opts.scale + local glasses = device['plethora:glasses'] + local canvas = glasses.canvas() + local _, cy = 1, 1 + local lines = { } + local pal = Glasses.getPalette(opts.opacity) local pos = { x = opts.x * xs, y = opts.y * ys } @@ -77,8 +83,8 @@ function Glasses.create(args) blit = function(text, fg, bg) for x = 1, #text do local ln = lines[cy] - ln.bg[x].setColor(map[bg:sub(x, x)]) - ln.text[x].setColor(map[fg:sub(x, x)]) + ln.bg[x].setColor(pal[bg:sub(x, x)]) + ln.text[x].setColor(pal[fg:sub(x, x)]) ln.text[x].setText(text:sub(x, x)) end end, diff --git a/neural/autorun/splash.lua b/neural/autorun/splash.lua index b74f722..ac92708 100644 --- a/neural/autorun/splash.lua +++ b/neural/autorun/splash.lua @@ -1,7 +1,10 @@ +local device = _G.device +local kernel = _G.kernel + local opus = { 'fffff00', 'ffff07000', - 'ff00770b00 4444', + 'ff00770b00f4444', 'ff077777444444444', 'f07777744444444444', 'f0000777444444444', @@ -12,29 +15,14 @@ local opus = { '077000000000', } -local hex = { - ['0'] = 0xF0F0F04F, - ['1'] = 0xF2B2334F, - ['2'] = 0xE57FD84F, - ['3'] = 0x99B2F24F, - ['4'] = 0xDEDE6C4F, - ['5'] = 0x7FCC194F, - ['6'] = 0xF2B2CC4F, - ['7'] = 0x4C4C4C4F, - ['8'] = 0x9999994F, - ['9'] = 0x4C99B24F, - ['a'] = 0xB266E54F, - ['b'] = 0x3366CC4F, - ['c'] = 0x7F664C4F, - ['d'] = 0x57A64E4F, - ['e'] = 0xCC4C4C4F, --- ['f'] = 0x191919FF, -- transparent -} - local function update() - local canvas = device['plethora:glasses'] and device['plethora:glasses'].canvas() + local canvas = device['plethora:glasses'] and device['plethora:glasses'].canvas() if canvas then - local Tween = require('opus.ui.tween') + local Tween = require('opus.ui.tween') + local Glasses = require('neural.glasses') + + local pal = Glasses.getPalette(0x4f) + pal['f'] = nil -- transparent canvas.clear() local w, h = canvas.getSize() @@ -42,7 +30,7 @@ local function update() local group = canvas.addGroup(pos) local function drawLine(k, line) for i = 1, #line do - local pix = hex[line:sub(i, i)] + local pix = pal[line:sub(i, i)] if pix then group.addRectangle(i*1.5, k*2.25, 1.5, 2.25, pix) end @@ -63,8 +51,6 @@ local function update() end kernel.run({ - title = 'opus', - env = _ENV, hidden = true, fn = update, }) diff --git a/neural/etc/apps.db b/neural/etc/apps.db index 31c01d7..f61f97a 100644 --- a/neural/etc/apps.db +++ b/neural/etc/apps.db @@ -3,12 +3,14 @@ title = "ElytraFly", category = "Neural", run = "elytraFly.lua", + iconExt = "\30\55\31\50\131\30\56\31\55\135\30\55\31\56\148\30\50\31\55\140\30\56\151\139\30\55\31\50\131\10\30\55\31\56\138\30\56\128\30\55\149\30\50\31\50\128\30\56\31\55\149\31\56\128\30\55\133\10\30\50\31\55\138\30\55\31\56\139\30\50\31\55\159\31\50\128\30\55\144\31\56\135\30\50\31\55\133", requires = "neuralInterface", }, [ "0d57bd5497ca26a92593094bf3e21c5097192fa3" ] = { title = "Fisher", category = "Neural", run = "fisher.lua", + iconExt = "\30\50\31\50\128\128\128\30\99\135\30\55\31\99\135\30\50\31\50\128\10\30\50\31\50\128\30\99\159\30\50\31\99\158\129\30\55\31\50\149\30\50\128\10\30\99\31\50\135\30\50\31\99\135\31\50\128\31\48\140\31\55\129\31\50\128", requires = "neuralInterface", }, [ "9101fc1744ab274aaa0b54ee22b14ca53ee6e236" ] = { @@ -27,12 +29,22 @@ title = "Ores", category = "Neural", run = "ores.lua", + iconExt = "\30\50\31\50\128\30\48\135\30\51\31\48\131\145\30\50\31\51\144\31\50\128\10\30\48\31\50\149\31\51\151\30\51\31\48\131\31\57\138\30\57\31\51\147\30\50\31\50\128\10\30\50\31\50\128\31\51\139\30\57\140\134\30\50\31\57\129\31\50\128", requires = "neuralInterface", }, [ "7f2465ac7cefab2766e6ee0714647089df9364b0ff09858c84b21b8a436a845d" ] = { title = "Equipment", category = "Neural", run = "Equipment", + iconExt = "\30\55\31\50\151\30\48\31\55\135\30\51\131\131\30\57\131\30\55\31\57\144\30\50\31\50\128\10\30\55\31\50\149\31\51\151\30\50\31\55\135\131\30\55\31\57\130\149\30\50\31\50\128\10\30\50\31\55\130\131\31\50\128\128\31\55\130\131\31\50\128", requires = "neuralInterface", - } + }, + [ "b492db2750ce6e21640a530c75a39ee7a6ac411e5962b6d96d27572784cd8ab4" ] = { + title = "Nwm", + category = "Neural", + iconExt = "\30\50\31\50\128\31\99\140\144\31\50\128\31\99\136\30\99\31\50\155\30\50\128\128\ +\30\50\31\50\128\128\31\99\137\30\102\31\102\128\30\50\132\30\102\31\50\145\30\50\31\102\157\31\50\128\ +\30\50\31\50\128\128\128\128\128\128\128\128", + run = "nwm.lua", + }, } diff --git a/neural/mobFollow.lua b/neural/mobFollow.lua index 1ef1601..b14818a 100644 --- a/neural/mobFollow.lua +++ b/neural/mobFollow.lua @@ -3,6 +3,11 @@ local Util = require('opus.util') local Point = require('opus.point') local Proxy = require('core.proxy') +--[[ + Have a mob follow you. The mob's neural must have the + neural package installed. +]] + local os = _G.os local args = { ... } diff --git a/neural/neuralLook.lua b/neural/neuralLook.lua index 9a35c78..c2dbbf5 100644 --- a/neural/neuralLook.lua +++ b/neural/neuralLook.lua @@ -2,6 +2,11 @@ local Array = require('opus.array') local neural = require('neural.interface') local Point = require('opus.point') +--[[ + Animate an armor stand or mob. Will just look + at anything that moves. +]] + local os = _G.os neural.assertModules({ diff --git a/neural/neuralRecorder.lua b/neural/neuralRecorder.lua index b1484f6..9966706 100644 --- a/neural/neuralRecorder.lua +++ b/neural/neuralRecorder.lua @@ -2,6 +2,10 @@ local GPS = require('opus.gps') local Point = require('opus.point') local Util = require('opus.util') +--[[ + Record your movements for playback on another mob. +]] + local os = _G.os local parallel = _G.parallel local peripheral = _G.peripheral diff --git a/neural/nwm.lua b/neural/nwm.lua index 91d2fe5..b1d230e 100644 --- a/neural/nwm.lua +++ b/neural/nwm.lua @@ -87,9 +87,6 @@ local function hook(e, eventData) return true end -local hookEvents = Util.keys(events) -kernel.hook(hookEvents, hook) - local function run(args) local window = Glasses.create(args) @@ -190,6 +187,9 @@ UI:setPage(UI.Page { end, }) +local hookEvents = Util.keys(events) +kernel.hook(hookEvents, hook) + for _,v in pairs(config.session) do run(v) end -- 2.49.1 From ad4cc5884fecea554d9d53ecc37fbcd72fac0f72 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Fri, 8 May 2020 22:31:06 -0600 Subject: [PATCH 04/19] editor/nwm bug fixes --- common/edit.lua | 27 ++++++++++++++------------- neural/nwm.lua | 12 +++++------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/common/edit.lua b/common/edit.lua index 27784e1..ee61066 100644 --- a/common/edit.lua +++ b/common/edit.lua @@ -9,7 +9,7 @@ local fs = _G.fs local multishell = _ENV.multishell local os = _G.os local shell = _ENV.shell -local term = _G.term +local term = _G.term.current() local textutils = _G.textutils local _format = string.format @@ -318,7 +318,7 @@ local page = UI.Page { show = function(self) local t = { } for _,v in pairs(config.recent or { }) do - table.insert(t, { name = fs.getName(v), dir = fs.getDir(v), path = v }) + _insert(t, { name = fs.getName(v), dir = fs.getDir(v), path = v }) end self.grid:setValues(t) self.grid:setIndex(1) @@ -453,10 +453,9 @@ local page = UI.Page { event = 'slide_hide', }, show = function(self, values) - local m = 12 - for _, v in pairs(values) do - m = #v.text > m and #v.text or m - end + local m = Util.reduce(values, function(m, v) + return #v.text > m and #v.text or m + end, 12) m = m + 3 m = m > self.parent.width and self.parent.width or m self.ox = -m @@ -492,7 +491,9 @@ local page = UI.Page { scan = function(self) self.values = { } for k, v in pairs(device) do - table.insert(self.values, { name = k, complete = 'peripheral.wrap("' .. v.side .. '")' }) + if type(v.side) == 'string' then + _insert(self.values, { name = k, complete = 'peripheral.wrap("' .. v.side .. '")' }) + end end end, postInit = function(self) @@ -519,7 +520,7 @@ local page = UI.Page { for k, v in pairs(dev) do if type(v) == 'function' then local m = docs and docs[k] and docs[k]:match('^function%((.+)%).+') - table.insert(t, { method = k, complete = k .. '(' .. (m or '') .. ')' }) + _insert(t, { method = k, complete = k .. '(' .. (m or '') .. ')' }) end end end) @@ -648,9 +649,9 @@ local function getFileInfo(path) config.recent = config.recent or { } Array.removeByValue(config.recent, path) - table.insert(config.recent, 1, path) + _insert(config.recent, 1, path) while #config.recent > 10 do - table.remove(config.recent) + _remove(config.recent) end Config.update('editor', config) @@ -763,7 +764,7 @@ actions = { local last = _remove(undo.chain) if last then undo.active = true - table.insert(undo.redo, { }) + _insert(undo.redo, { }) for i = #last, 1, -1 do local u = last[i] actions[u.action](_unpack(u.args)) @@ -777,14 +778,14 @@ actions = { undo_add = function(entry) if undo.active then local last = undo.redo[#undo.redo] - table.insert(last, entry) + _insert(last, entry) else if not undo.redo_active then undo.redo = { } end local last = undo.chain[#undo.chain] if last and undo.continue then - table.insert(last, entry) + _insert(last, entry) else _insert(undo.chain, { entry }) end diff --git a/neural/nwm.lua b/neural/nwm.lua index b1d230e..00154f8 100644 --- a/neural/nwm.lua +++ b/neural/nwm.lua @@ -76,7 +76,7 @@ local function hook(e, eventData) if clickedTab then if clickedTab ~= currentTab then clickedTab.window.raise() - multishell.setFocus(clickedTab.uid) + kernel.raise(clickedTab.uid) end kernel.event(events[e], { @@ -88,8 +88,6 @@ local function hook(e, eventData) end local function run(args) - local window = Glasses.create(args) - local titleBar = Glasses.create({ x = args.x, y = args.y - 1, @@ -102,17 +100,17 @@ local function run(args) titleBar.canvas:write(args.width - 2, 1, ' x ', nil, 'black') titleBar.redraw() - multishell.openTab({ + kernel.run({ path = args.path, args = args.args, hidden = true, - onDestroy = function() + onExit = function(self) Util.removeByValue(config.session, args) Config.update('nwm', config) - window.destroy() + self.window.destroy() titleBar.destroy() end, - window = window, + window = Glasses.create(args), titleBar = titleBar, wmargs = args, }) -- 2.49.1 From d902acacf4c7f18933a1b581ae5fa01ea25a778f Mon Sep 17 00:00:00 2001 From: Luca S Date: Sun, 10 May 2020 07:48:39 +0200 Subject: [PATCH 05/19] Add a Defragment button to Milo (#36) --- milo/apis/storage.lua | 128 ++++++++++++++++++++++++++++++++++++++++++ milo/core/listing.lua | 18 ++++++ 2 files changed, 146 insertions(+) diff --git a/milo/apis/storage.lua b/milo/apis/storage.lua index dfd2061..a4d19c4 100644 --- a/milo/apis/storage.lua +++ b/milo/apis/storage.lua @@ -291,6 +291,134 @@ function Storage:listItems(throttle) return self.cache end +-- provide a raw list of all the items in all storage chests +-- it might be beneficial to move this to the adapter class at some point and cache the raw item list in this class at some point +function Storage:listItemsRaw(throttle) + local res = {} + + throttle = throttle or Util.throttle() + + for _, v in pairs(self.nodes) do + if v.category == "storage" then + local chest = device[v.name] + local items = chest.list() + + for slot, item in pairs(items) do + items[slot] = itemDB:get(item, function() return chest.getItemMeta(slot) end) + end + + res[v.name] = items + throttle() + end + end + + return res +end + +-- provide a list of items and which chests provide them +function Storage:listProviders(throttle) + local res = {} + + local rawItems = self:listItemsRaw(throttle) + + for chest, items in pairs(rawItems) do + for slot, item in pairs(items) do + local key = table.concat({item.name, item.damage, item.nbtHash}, ":") + if not res[key] then + res[key] = {} + end + table.insert(res[key], {item = item, device = device[chest], lockedToThis = (self.nodes[chest].lock or {})[key] or false, slot = slot}) + end + end + return res +end + +-- defrags the storage system +function Storage:defrag(throttle) + local items = self:listProviders(throttle) + local slotsSaved = 0 + + -- This will make sure the table is sorted in the following order: + -- Unlocked stacks with less than maxCount items | Locked stacks with less than maxCount items | stacks with more than maxCount items + -- This way the locked stacks will be filled first + local function sortFunction(a, b) + local preferenceA, preferenceB + preferenceA = (a.item.count == a.item.maxCount and 3) + or (a.lockedToThis and 2) + or 1 + preferenceB = (b.item.count == b.item.maxCount and 3) + or (b.lockedToThis and 2) + or 1 + + if preferenceA < preferenceB then + return true + elseif preferenceB > preferenceA then + return false + else + return a.item.count < b.item.count + end + end + + for _, providers in pairs(items) do + table.sort(providers, sortFunction) + + -- We're done when we either compressed the stacks so far, that there's only one left (#providers == 1) + -- Or when we've compressed so far, that the there's only one stack which has a lower count than the maxCount + -- Because of the sorting, we know that this will be the stack in providers[1], so we check if providers[2] is at the maxCount + while #providers > 1 and providers[2].item.count ~= providers[2].item.maxCount do + local from = providers[1] + local to + + -- We're pushing to the highest stack which is still below the maxCount, this way as many slots as possible will be filled + -- This loop is guarenteed to assign a value to "to", as the only cases where it wouldn't (#providers == 1 or no provider with less than maxCount) + -- are ruled out by the condition of the outer while loop + for i = 2, #providers do + -- Give preference to locked chests + if not (to and to.lockedToThis or false) and providers[i].lockedToThis then + to = providers[i] + elseif ((to and to.lockedToThis or false) == providers[i].lockedToThis) and providers[i].item.count < providers[i].item.maxCount then + to = providers[i] + elseif providers[i].item.count == providers[i].item.maxCount then + -- As this slot is already at maxCount, all the remaining ones will also be due to sorting + -- If any of the remaining providers is locked that doesn't matter. We wouldn't have been able to push there anyways + break + end + end + + local toMove = math.min(to.item.maxCount - to.item.count, from.item.count) + local s, m = pcall(function() + from.device.pushItems(to.device.name, from.slot, toMove, to.slot) + end) + + if not s and m then + _G._syslog(m) + end + + if s then + to.item.count = to.item.count + toMove + from.item.count = from.item.count - toMove + else + -- Do not try to send to the target again after it failed + for i = 2, #providers do + if to == providers[i] then + table.remove(providers, i) + break + end + end + end + + if from.item.count <= 0 then + table.remove(providers, 1) + slotsSaved = slotsSaved + 1 + end + + table.sort(providers, sortFunction) + end + end + + return slotsSaved +end + function Storage:updateCache(adapter, item, count) if not adapter.cache then adapter.dirty = true diff --git a/milo/core/listing.lua b/milo/core/listing.lua index 34f1b6c..eefff37 100644 --- a/milo/core/listing.lua +++ b/milo/core/listing.lua @@ -33,6 +33,11 @@ local page = UI.Page { event = 'rescan', help = 'Rescan all inventories' }, + { + text = 'Defragment storage', + event = 'defrag', + help = 'Defragments the storage' + } }, }, }, @@ -250,6 +255,10 @@ function page:eventHandler(event) self.grid:draw() self:setFocus(self.statusBar.filter) + elseif event.type == 'defrag' then + self:defrag() + self:refresh(true) + elseif event.type == 'toggle_display' then displayMode = (displayMode + 1) % 2 Util.merge(event.button, displayModes[displayMode]) @@ -357,6 +366,15 @@ function page:refresh(force) self.throttle:disable() end +function page:defrag() + local throttle = function() self.throttle:update() end + + self.throttle:enable() + local saved = context.storage:defrag(throttle) + self.throttle:disable() + self:notifyInfo(("Saved %d slots"):format(saved)) +end + function page:applyFilter() local function filterItems(t, filter) self.grid.sortColumn = Milo:getState('sortColumn') or 'count' -- 2.49.1 From 759e4e2b958f96600aa9455851e60276c1012c95 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Sun, 10 May 2020 14:04:42 -0600 Subject: [PATCH 06/19] cleanup --- common/Devices.lua | 2 +- common/recorder.lua | 10 +++++----- monitor/mirrorClient.lua | 3 +-- neural/nwm.lua | 17 +++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/common/Devices.lua b/common/Devices.lua index 7710bd5..c9c5556 100644 --- a/common/Devices.lua +++ b/common/Devices.lua @@ -132,7 +132,7 @@ end function methodsPage:getDocumentation() local method = self.grid:getSelected() - if method.noext then -- computercraft docs + if not method or method.noext then -- computercraft docs return 'No documentation' end diff --git a/common/recorder.lua b/common/recorder.lua index 4ea8824..86dfc3c 100644 --- a/common/recorder.lua +++ b/common/recorder.lua @@ -23,7 +23,7 @@ local colours = _G.colors local args, options = Util.parse(...) -local oldTerm, showInput, skipLast, lastDelay, curInput = Util.shallowCopy(multishell.term), false, false, 2, "" +local oldTerm, showInput, skipLast, lastDelay, curInput = Util.shallowCopy(_G.device.terminal), false, false, 2, "" local curBlink, oldBlink, tTerm, buffer, colourNum, xPos, yPos, oldXPos, oldYPos, tCol, bCol, xSize, ySize = false, false, {}, {}, {}, 1, 1, 1, 1, colours.white, colours.black, oldTerm.getSize() local greys, buttons = {["0"] = true, ["7"] = true, ["8"] = true, ["f"] = true}, {"l", "r", "m"} local charW, charH, chars @@ -60,7 +60,7 @@ if options.help then end if options.daemon then - device.keyboard.addHotkey('control-P', function() + _G.device.keyboard.addHotkey('control-P', function() multishell.openTab({ path = 'sys/apps/shell.lua', args = { arg[0], '--noResize', '--rawOutput', 'recorder.gif' }, @@ -141,7 +141,7 @@ end -- Build a terminal that records stuff: -local recTerm = multishell.term +local recTerm = _G.device.terminal for key, func in pairs(oldTerm) do if type(func) == 'function' then @@ -153,7 +153,7 @@ for key, func in pairs(oldTerm) do end callCount = callCount + 1 curCalls[callCount] = { key, ... } - return unpack(result) + return table.unpack(result) end end end @@ -196,7 +196,7 @@ end _G.device.keyboard.removeHotkey('control-p') for k,fn in pairs(oldTerm) do - multishell.term[k] = fn + _G.device.terminal[k] = fn end multishell.unhideTab(tabId) diff --git a/monitor/mirrorClient.lua b/monitor/mirrorClient.lua index 2e1aca7..b7c8091 100644 --- a/monitor/mirrorClient.lua +++ b/monitor/mirrorClient.lua @@ -2,7 +2,6 @@ local Event = require('opus.event') local Socket = require('opus.socket') local Util = require('opus.util') -local multishell = _ENV.multishell local os = _G.os local remoteId @@ -23,7 +22,7 @@ local function wrapTerm(socket) 'setTextColor', 'setTextColour', 'setBackgroundColor', 'setBackgroundColour', 'scroll', 'setCursorBlink', } - socket.term = multishell.term + socket.term = _G.device.terminal socket.oldTerm = Util.shallowCopy(socket.term) for _,k in pairs(methods) do diff --git a/neural/nwm.lua b/neural/nwm.lua index 00154f8..0fa4d29 100644 --- a/neural/nwm.lua +++ b/neural/nwm.lua @@ -31,10 +31,10 @@ local events = { } local function hook(e, eventData) - local currentTab = kernel.getFocused() + local current = kernel.getFocused() local x = math.floor(eventData[2] / xs) local y = math.floor(eventData[3] / ys) - local clickedTab + local clicked if dragging then if e == 'glasses_up' then @@ -58,7 +58,7 @@ local function hook(e, eventData) local ww, wh = tab.window.getSize() if x >= wx and x <= wx + ww and y > wy and y < wy + wh then - clickedTab = tab + clicked = tab x = x - wx y = y - wy break @@ -73,14 +73,14 @@ local function hook(e, eventData) end end - if clickedTab then - if clickedTab ~= currentTab then - clickedTab.window.raise() - kernel.raise(clickedTab.uid) + if clicked then + if clicked ~= current then + clicked.window.raise() + kernel.raise(clicked.uid) end kernel.event(events[e], { - eventData[1], x, y, clickedTab.window.side, + eventData[1], x, y, clicked.window.side, }) end @@ -104,6 +104,7 @@ local function run(args) path = args.path, args = args.args, hidden = true, + title = fs.getName(args.path), onExit = function(self) Util.removeByValue(config.session, args) Config.update('nwm', config) -- 2.49.1 From ad32dcc2df408567782f4cbcf855123711ceeee1 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Mon, 11 May 2020 17:26:43 -0600 Subject: [PATCH 07/19] updates for environment handling changes --- common/Appstore.lua | 5 +- common/Events.lua | 2 +- common/Turtles.lua | 6 +- common/debugMonitor.lua | 1 + common/edit.lua | 4 +- common/etc/scripts/goHome | 1 - common/etc/scripts/moveTo.lua | 2 - common/etc/scripts/setHome | 1 - common/etc/scripts/summon | 3 - common/recorder.lua | 2 +- monitor/mwm.lua | 18 ++--- neural/Scanner.lua | 2 +- neural/autorun/splash.lua | 2 +- neural/nwm.lua | 134 ++++++++++++++++++++++--------- screenSaver/autorun/saver.lua | 2 +- secure/autorun/lock.lua | 144 +++++++++++++++++----------------- secure/unlock.lua | 20 ++--- 17 files changed, 200 insertions(+), 149 deletions(-) diff --git a/common/Appstore.lua b/common/Appstore.lua index 7e0ad85..8e87ef1 100644 --- a/common/Appstore.lua +++ b/common/Appstore.lua @@ -57,7 +57,7 @@ local function downloadApp(app) end local function runApp(app, checkExists, ...) - local env = shell.makeEnv() + local env = shell.makeEnv(_ENV) local path, fn local args = { ... } @@ -83,9 +83,8 @@ local function runApp(app, checkExists, ...) end end - multishell.openTab({ + multishell.openTab(_ENV, { title = app.name, - env = env, path = path, fn = fn, focused = true, diff --git a/common/Events.lua b/common/Events.lua index ae58ca2..f2539af 100644 --- a/common/Events.lua +++ b/common/Events.lua @@ -67,7 +67,7 @@ local page = UI.Page { self.menuBar:draw() elseif event.type == 'grid_select' then - multishell.openTab({ + multishell.openTab(_ENV, { path = 'sys/apps/Lua.lua', args = { event.selected }, focused = true, diff --git a/common/Turtles.lua b/common/Turtles.lua index 07d89e6..66c6a54 100644 --- a/common/Turtles.lua +++ b/common/Turtles.lua @@ -223,7 +223,7 @@ page = UI.Page { fn = 'turtle.turnRight', }, info = UI.TextArea { - x = 15, y = 2, + x = 15, y = 1, inactive = true, }, showBlocks = function(self) @@ -240,13 +240,13 @@ page = UI.Page { return string.format('%s\n%s\n%s', bu, bf, bd) ]] - local s, m = self:runFunction(script, true) + local s, m = page:runFunction(script, true) self.info:setText(s or m) end, eventHandler = function(self, event) if event.type == 'button_press' then if event.button.fn then - self:runFunction(event.button.fn, event.button.nowrap) + page:runFunction(event.button.fn, event.button.nowrap) self:showBlocks() end return true diff --git a/common/debugMonitor.lua b/common/debugMonitor.lua index d198f77..949375a 100644 --- a/common/debugMonitor.lua +++ b/common/debugMonitor.lua @@ -24,6 +24,7 @@ _G._syslog = function(...) local oldTerm = term.redirect(mon) Util.print(...) term.redirect(oldTerm) + oldDebug(...) end repeat diff --git a/common/edit.lua b/common/edit.lua index ee61066..d702e1f 100644 --- a/common/edit.lua +++ b/common/edit.lua @@ -1024,7 +1024,7 @@ actions = { else local fn, msg = load(_concat(tLines, '\n'), fileInfo.path) if fn then - multishell.openTab({ + multishell.openTab(_ENV, { fn = fn, focused = true, title = fs.getName(fileInfo.path), @@ -1544,5 +1544,5 @@ local s, m = pcall(function() UI:start() end) if not s then actions.save('/crash.txt') print('Editor has crashed. File saved as /crash.txt') - error(m) + error(m, -1) end diff --git a/common/etc/scripts/goHome b/common/etc/scripts/goHome index 94fd138..6e12c25 100644 --- a/common/etc/scripts/goHome +++ b/common/etc/scripts/goHome @@ -1,4 +1,3 @@ -_G.requireInjector(_ENV) local config = require('opus.config').load('gps') if config.home then if turtle.enableGPS() then diff --git a/common/etc/scripts/moveTo.lua b/common/etc/scripts/moveTo.lua index 72d597a..f62520e 100644 --- a/common/etc/scripts/moveTo.lua +++ b/common/etc/scripts/moveTo.lua @@ -1,8 +1,6 @@ local turtle = _G.turtle turtle.run(function() - _G.requireInjector(_ENV) - local GPS = require('opus.gps') if not turtle.enableGPS() then diff --git a/common/etc/scripts/setHome b/common/etc/scripts/setHome index be69170..2b347a7 100644 --- a/common/etc/scripts/setHome +++ b/common/etc/scripts/setHome @@ -1,4 +1,3 @@ -_G.requireInjector(_ENV) local Config = require('opus.config') local pt = turtle.enableGPS() if pt then diff --git a/common/etc/scripts/summon b/common/etc/scripts/summon index 66dcded..17c514c 100644 --- a/common/etc/scripts/summon +++ b/common/etc/scripts/summon @@ -1,7 +1,4 @@ local function summon(id) - - _G.requireInjector(_ENV) - local GPS = require('opus.gps') local Point = require('opus.point') local Socket = require('opus.socket') diff --git a/common/recorder.lua b/common/recorder.lua index 86dfc3c..bd5e7d5 100644 --- a/common/recorder.lua +++ b/common/recorder.lua @@ -61,7 +61,7 @@ end if options.daemon then _G.device.keyboard.addHotkey('control-P', function() - multishell.openTab({ + multishell.openTab(_ENV, { path = 'sys/apps/shell.lua', args = { arg[0], '--noResize', '--rawOutput', 'recorder.gif' }, }) diff --git a/monitor/mwm.lua b/monitor/mwm.lua index 9eda98f..73ec2ee 100644 --- a/monitor/mwm.lua +++ b/monitor/mwm.lua @@ -1,3 +1,4 @@ +local Alt = require('opus.alternate') local Terminal = require('opus.terminal') local trace = require('opus.trace') local Util = require('opus.util') @@ -25,8 +26,7 @@ local monName = args[1] local running local parentMon -local defaultEnv = Util.shallowCopy(_ENV) -defaultEnv.multishell = multishell +_ENV.multishell = multishell if monName then parentMon = peripheral.wrap(monName) or syntax() else @@ -93,8 +93,8 @@ end --[[ A runnable process ]]-- local Process = { } -function Process:new(args) - args.env = args.env or Util.shallowCopy(defaultEnv) +function Process:new(env, args) + args.env = shell.makeEnv(env) args.width = args.width or termDim.width args.height = args.height or termDim.height @@ -329,7 +329,7 @@ function multishell.getTabs() end function multishell.launch(env, file, ...) - return multishell.openTab({ + return multishell.openTab(env, { path = file, env = env, title = 'shell', @@ -337,8 +337,8 @@ function multishell.launch(env, file, ...) }) end -function multishell.openTab(tabInfo) - local process = Process:new(tabInfo) +function multishell.openTab(env, tabInfo) + local process = Process:new(env, tabInfo) table.insert(processes, 1, process) @@ -380,7 +380,7 @@ function multishell.loadSession(filename) local config = Util.readTable(filename) if config then for k = #config, 1, -1 do - multishell.openTab(config[k]) + multishell.openTab(_ENV, config[k]) end end end @@ -497,7 +497,7 @@ local function addShell() process.co = coroutine.create(function() print('To run a program on the monitor, type "fg "') print('To quit, type "exit"') - os.run(Util.shallowCopy(defaultEnv), shell.resolveProgram('shell')) + os.run(shell.makeEnv(_ENV), Alt.get('shell')) multishell.stop() end) diff --git a/neural/Scanner.lua b/neural/Scanner.lua index 4dd6be5..5debfd7 100644 --- a/neural/Scanner.lua +++ b/neural/Scanner.lua @@ -188,7 +188,7 @@ function page:eventHandler(event) self:scan() elseif event.type == 'grid_select' and event.element == self.detail.grid then - multishell.openTab({ + multishell.openTab(_ENV, { path = 'sys/apps/Lua.lua', args = { event.selected }, focused = true, diff --git a/neural/autorun/splash.lua b/neural/autorun/splash.lua index ac92708..e5b32d9 100644 --- a/neural/autorun/splash.lua +++ b/neural/autorun/splash.lua @@ -50,7 +50,7 @@ local function update() end end -kernel.run({ +kernel.run(_ENV, { hidden = true, fn = update, }) diff --git a/neural/nwm.lua b/neural/nwm.lua index 0fa4d29..6100cd0 100644 --- a/neural/nwm.lua +++ b/neural/nwm.lua @@ -11,10 +11,11 @@ local Glasses = require('neural.glasses') local UI = require('opus.ui') local Util = require('opus.util') -local fs = _G.fs -local kernel = _G.kernel -local multishell = _ENV.multishell -local shell = _ENV.shell +local device = _G.device +local fs = _G.fs +local kernel = _G.kernel +local shell = _ENV.shell +local window = _G.window local config = Config.load('nwm', { session = { } }) @@ -22,6 +23,14 @@ local config = Config.load('nwm', { session = { } }) local scale = .5 local xs, ys = 6 * scale, 9 * scale local dragging +local canvas = device['plethora:glasses'].canvas() +local cw, ch = canvas.getSize() +local opacity = 127 + +local multishell = Util.shallowCopy(_ENV.multishell) +_ENV.multishell = multishell + +cw, ch = cw / xs, ch / ys local events = { glasses_click = 'mouse_click', @@ -42,7 +51,7 @@ local function hook(e, eventData) elseif e == 'glasses_drag' then local dx = x - dragging.ax local dy = y - dragging.ay - dragging.tab.window.move(dragging.wx + dx, dragging.wy + dy) + dragging.tab.gwindow.move(dragging.wx + dx, dragging.wy + dy) dragging.tab.titleBar.move(dragging.wx + dx, dragging.wy + dy - 1) dragging.tab.wmargs.x = dragging.wx + dx @@ -53,9 +62,9 @@ local function hook(e, eventData) end for _,tab in ipairs(kernel.routines) do - if tab.window.type == 'glasses' then - local wx, wy = tab.window.getPosition() - local ww, wh = tab.window.getSize() + if tab.gwindow then + local wx, wy = tab.gwindow.getPosition() + local ww, wh = tab.gwindow.getSize() if x >= wx and x <= wx + ww and y > wy and y < wy + wh then clicked = tab @@ -75,46 +84,90 @@ local function hook(e, eventData) if clicked then if clicked ~= current then - clicked.window.raise() + clicked.gwindow.raise() kernel.raise(clicked.uid) end kernel.event(events[e], { - eventData[1], x, y, clicked.window.side, + eventData[1], x, y, clicked.gwindow.side, }) end return true end -local function run(args) +function multishell.openTab(env, tab) + if not tab.wmargs then + tab.wmargs = { + x = math.random(1, cw - 51 + 1), + y = math.random(1, ch - 19 + 1), + width = 51, + height = 19, + opacity = opacity, + path = tab.path, + args = tab.args, + } + table.insert(config.session, tab.wmargs) + Config.update('nwm', config) + else + tab.path = tab.wmargs.path + tab.args = tab.wmargs.args + end + + if tab.path ~= 'sys/apps/shell.lua' then + if tab.args and #tab.args > 0 then + tab.args = { tab.path .. ' ' .. table.concat(tab.args or { }, ' ') } + else + tab.args = { tab.path } + end + tab.path = 'sys/apps/shell.lua' + end + + local wmargs = tab.wmargs + local titleBar = Glasses.create({ - x = args.x, - y = args.y - 1, + x = wmargs.x, + y = wmargs.y - 1, height = 1, - width = args.width, - opacity = args.opacity, + width = wmargs.width, + opacity = wmargs.opacity, }) titleBar.canvas:clear('yellow') - titleBar.canvas:write(1, 1, ' ' .. fs.getName(args.path), nil, 'black') - titleBar.canvas:write(args.width - 2, 1, ' x ', nil, 'black') + titleBar.canvas:write(1, 1, ' ' .. fs.getName(tab.path), nil, 'black') + titleBar.canvas:write(wmargs.width - 2, 1, ' x ', nil, 'black') titleBar.redraw() - kernel.run({ - path = args.path, - args = args.args, - hidden = true, - title = fs.getName(args.path), - onExit = function(self) - Util.removeByValue(config.session, args) - Config.update('nwm', config) - self.window.destroy() - titleBar.destroy() - end, - window = Glasses.create(args), - titleBar = titleBar, - wmargs = args, - }) + if not tab.title and tab.path then + tab.title = fs.getName(tab.path):match('([^%.]+)') + end + tab.hidden = true + tab.title = tab.title or 'untitled' + + local w, h = device.terminal.getSize() + tab.window = window.create(device.terminal, 1, 2, w, h - 1, false) + tab.gwindow = Glasses.create(wmargs) + tab.terminal = tab.gwindow + tab.titleBar = titleBar + tab.onExit = tab.onExit or function(self) + Util.removeByValue(config.session, tab.wmargs) + Config.update('nwm', config) + self.gwindow.destroy() + self.titleBar.destroy() + end + + local routine, message = kernel.run(env, tab) + return routine and routine.uid, message +end + +function multishell.setTitle(tabId, title) + local tab = kernel.find(tabId) + if tab then + tab.title = title + tab.titleBar.canvas:clear('yellow') + tab.titleBar.canvas:write(1, 1, ' ' .. title, nil, 'black') + tab.titleBar.canvas:write(tab.wmargs.width - 2, 1, ' x ', nil, 'black') + tab.titleBar.redraw() + end end UI:setPage(UI.Page { @@ -131,6 +184,12 @@ UI:setPage(UI.Page { formLabel = 'Opacity', formKey = 'opacity', formIndex = 3, labelWidth = 3, transform = math.floor, + eventHandler = function(self, event) + if event.type == 'slider_update' then + opacity = event.value + end + return UI.Slider.eventHandler(self, event) + end, }, UI.Text { x = 10, y = 5, @@ -168,14 +227,15 @@ UI:setPage(UI.Page { if event.type == 'form_complete' then local opts = Util.shallowCopy(event.values) local words = Util.split(opts.run, '(.-) ') - opts.path = shell.resolveProgram(table.remove(words, 1)) - if not opts.path then + words[1] = shell.resolveProgram(words[1]) + if not words[1] then self.notification:error('Invalid program') else - opts.args = #words > 0 and words + opts.path = 'sys/apps/shell.lua' + opts.args = table.concat(words, ' ') table.insert(config.session, opts) Config.update('nwm', config) - run(opts) + multishell.openTab(_ENV, { wmargs = opts }) self.notification:success('Started program') end @@ -190,7 +250,7 @@ local hookEvents = Util.keys(events) kernel.hook(hookEvents, hook) for _,v in pairs(config.session) do - run(v) + multishell.openTab(_ENV, { wmargs = v }) end UI:start() diff --git a/screenSaver/autorun/saver.lua b/screenSaver/autorun/saver.lua index db33bc6..318968a 100644 --- a/screenSaver/autorun/saver.lua +++ b/screenSaver/autorun/saver.lua @@ -31,7 +31,7 @@ local function showScreenSaver() local w, h = kernel.terminal.getSize() local win = window.create(kernel.terminal, 1, 1, w, h, true) - saverUid = multishell.openTab({ + saverUid = multishell.openTab(_ENV, { path = saver, focused = true, title = 'Saver', diff --git a/secure/autorun/lock.lua b/secure/autorun/lock.lua index eadff4c..c71ac38 100644 --- a/secure/autorun/lock.lua +++ b/secure/autorun/lock.lua @@ -7,109 +7,107 @@ local keyboard = device.keyboard local multishell = _ENV.multishell if not multishell then - return + return end local config = Config.load('secure', { enabled = false, - timeout = 60, + timeout = 60, }) local timer = config.enabled and os.startTimer(config.timeout) local function buildLockScreen() - _G.requireInjector(_ENV) + local Event = require('opus.event') + local Security = require('opus.security') + local SHA = require('opus.crypto.sha2') + local UI = require('opus.ui') - local Event = require('opus.event') - local Security = require('opus.security') - local SHA = require('opus.crypto.sha2') - local UI = require('opus.ui') + local counter = .1 - local counter = .1 + local page = UI.Page { + pass = UI.TextEntry { + x = 10, ex = -10, y = "50%", + limit = 32, + mask = true, + shadowText = 'password', + accelerators = { + enter = 'password', + }, + }, + notification = UI.Notification(), + } + function page:eventHandler(event) + if event.type == 'password' then - local page = UI.Page { - pass = UI.TextEntry { - x = 10, ex = -10, y = "50%", - limit = 32, - mask = true, - shadowText = 'password', - accelerators = { - enter = 'password', - }, - }, - notification = UI.Notification(), - } - function page:eventHandler(event) - if event.type == 'password' then + if self.pass.value and + #self.pass.value > 0 and + Security.verifyPassword(SHA.compute(self.pass.value)) then - if self.pass.value and - #self.pass.value > 0 and - Security.verifyPassword(SHA.compute(self.pass.value)) then + UI:quit() -- valid + else + self.notification:error('Invalid password', math.max(counter, 2)) + self:sync() + os.sleep(counter) + counter = counter * 2 - UI:quit() -- valid - else - self.notification:error('Invalid password', math.max(counter, 2)) - self:sync() - os.sleep(counter) - counter = counter * 2 + self.pass:reset() + end + else + UI.Page.eventHandler(self, event) + end + end - self.pass:reset() - end - else - UI.Page.eventHandler(self, event) - end - end + Event.onTerminate(function() return false end) - Event.onTerminate(function() return false end) + UI:setPage(page) + UI:start() - UI:setPage(page) - UI:start() - - -- restart lock timer - timer = os.startTimer(config.timeout) + -- restart lock timer + timer = os.startTimer(config.timeout) end local function showLockScreen() - timer = nil - multishell.openTab({ - path = 'sys/apps/Lock.lua', - fn = buildLockScreen, - noTerminate = true, - pinned = true, - focused = true, - title = 'Lock', - }) + timer = nil + multishell.openTab(_ENV, { + path = 'sys/apps/Lock.lua', + fn = buildLockScreen, + noTerminate = true, + pinned = true, + focused = true, + title = 'Lock', + }) end keyboard.addHotkey('control-l', function() - if timer then - os.cancelTimer(timer) - showLockScreen() - end + if timer then + os.cancelTimer(timer) + showLockScreen() + end end) kernel.hook({ 'mouse_up', 'mouse_drag', 'key_up', 'mouse_scroll' }, function() - if timer then - os.cancelTimer(timer) - timer = os.startTimer(config.timeout) - end + if timer then + os.cancelTimer(timer) + timer = os.startTimer(config.timeout) + end end) kernel.hook('timer', function(_, eventData) - if timer and eventData[1] == timer then - showLockScreen() - end + if timer and eventData[1] == timer then + showLockScreen() + end end) kernel.hook('config_update', function(_, eventData) - if eventData[1] == 'secure' then - Util.merge(config, eventData[2]) - if timer then - os.cancelTimer(timer) - timer = nil - end - if config.enabled then - timer = os.startTimer(config.timeout) - end - end + if eventData[1] == 'secure' then + Util.merge(config, eventData[2]) + if timer then + os.cancelTimer(timer) + timer = nil + end + if config.enabled then + timer = os.startTimer(config.timeout) + end + end end) diff --git a/secure/unlock.lua b/secure/unlock.lua index 6fc5e58..0cdeb02 100644 --- a/secure/unlock.lua +++ b/secure/unlock.lua @@ -16,15 +16,15 @@ term.setCursorPos(1, 1) term.clear() repeat - local s, m = pcall(function() - local password = Terminal.readPassword('Enter password: ') + local s, m = pcall(function() + local password = Terminal.readPassword('Enter password: ') - if password and Security.verifyPassword(SHA.compute(password)) then - return true - end - error('Invalid password') - end) - if not s and m then - _G.printError(m) - end + if password and Security.verifyPassword(SHA.compute(password)) then + return true + end + error('Invalid password') + end) + if not s and m then + _G.printError(m) + end until s -- 2.49.1 From bc0cf883b40193365c819f6dcf69f649df1f2c86 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Tue, 12 May 2020 21:26:02 -0600 Subject: [PATCH 08/19] Improved error messages + nwm opacity/resizing --- monitor/mwm.lua | 3 +- neural/apis/glasses.lua | 77 +++++++++------ neural/apis/interface.lua | 10 +- neural/elytraFly.lua | 11 ++- neural/nwm.lua | 199 +++++++++++++++++--------------------- 5 files changed, 152 insertions(+), 148 deletions(-) diff --git a/monitor/mwm.lua b/monitor/mwm.lua index 73ec2ee..fa19aa1 100644 --- a/monitor/mwm.lua +++ b/monitor/mwm.lua @@ -12,8 +12,7 @@ local term = _G.term local window = _G.window local function syntax() - printError('Syntax:') - error('mwm [--config=filename] [monitor]') + error('Syntax:\nmwm [--config=filename] [monitor]') end local args = Util.parse(...) diff --git a/neural/apis/glasses.lua b/neural/apis/glasses.lua index 1fb398c..e529aa8 100644 --- a/neural/apis/glasses.lua +++ b/neural/apis/glasses.lua @@ -12,31 +12,32 @@ local device = _G.device local Glasses = { } +local palette = { + ['0'] = 0xF0F0F000, + ['1'] = 0xF2B23300, + ['2'] = 0xE57FD800, + ['3'] = 0x99B2F200, + ['4'] = 0xDEDE6C00, + ['5'] = 0x7FCC1900, + ['6'] = 0xF2B2CC00, + ['7'] = 0x4C4C4C00, + ['8'] = 0x99999900, + ['9'] = 0x4C99B200, + ['a'] = 0xB266E500, + ['b'] = 0x3366CC00, + ['c'] = 0x7F664C00, + ['d'] = 0x57A64E00, + ['e'] = 0xCC4C4C00, + ['f'] = 0x19191900, +} + function Glasses.getPalette(opacity) - local pal = { - ['0'] = 0xF0F0F000, - ['1'] = 0xF2B23300, - ['2'] = 0xE57FD800, - ['3'] = 0x99B2F200, - ['4'] = 0xDEDE6C00, - ['5'] = 0x7FCC1900, - ['6'] = 0xF2B2CC00, - ['7'] = 0x4C4C4C00, - ['8'] = 0x99999900, - ['9'] = 0x4C99B200, - ['a'] = 0xB266E500, - ['b'] = 0x3366CC00, - ['c'] = 0x7F664C00, - ['d'] = 0x57A64E00, - ['e'] = 0xCC4C4C00, - ['f'] = 0x19191900, - } if opacity then - for k,v in pairs(pal) do - pal[k] = v + opacity + for k,v in pairs(palette) do + palette[k] = v + opacity end end - return pal + return palette end function Glasses.create(args) @@ -54,7 +55,7 @@ function Glasses.create(args) local canvas = glasses.canvas() local _, cy = 1, 1 local lines = { } - local pal = Glasses.getPalette(opts.opacity) + local pal = palette -- Glasses.getPalette(opts.opacity) local pos = { x = opts.x * xs, y = opts.y * ys } @@ -83,9 +84,11 @@ function Glasses.create(args) blit = function(text, fg, bg) for x = 1, #text do local ln = lines[cy] - ln.bg[x].setColor(pal[bg:sub(x, x)]) - ln.text[x].setColor(pal[fg:sub(x, x)]) - ln.text[x].setText(text:sub(x, x)) + if ln and x <= opts.width then + ln.bg[x].setColor(pal[bg:sub(x, x)] + opts.opacity) + ln.text[x].setColor(pal[fg:sub(x, x)] + opts.opacity) + ln.text[x].setText(text:sub(x, x)) + end end end, setCursorPos = function(_, y) @@ -110,6 +113,13 @@ function Glasses.create(args) function gterm.getTextScale() return opts.scale end + function gterm.getOpacity() + return opts.opacity + end + function gterm.setOpacity(opacity) + opts.opacity = opacity + gterm.redraw() + end function gterm.move(x, y) if opts.x ~= x or opts.y ~= y then opts.x, opts.y = x, y @@ -117,10 +127,21 @@ function Glasses.create(args) group.setPosition(pos.x, pos.y) end end + function gterm.reposition2(x, y, w, h) + opts.x, opts.y = x, y + opts.width, opts.height = w, h + pos = { x = opts.x * xs, y = opts.y * ys } + local g = canvas.addGroup(pos) + init(g) + group.remove() + group = g + gterm.reposition(1, 1, w, h) + gterm.redraw() + end - gterm.name = opts.name - gterm.side = opts.name - gterm.type = 'glasses' + --gterm.name = opts.name + --gterm.side = opts.name + --gterm.type = 'glasses' return gterm end diff --git a/neural/apis/interface.lua b/neural/apis/interface.lua index 083b678..344b45b 100644 --- a/neural/apis/interface.lua +++ b/neural/apis/interface.lua @@ -17,12 +17,14 @@ function Neural.assertModules(modules) for _, m in pairs(modules) do if not Neural.hasModule(m) then - print('Required:') + local t = { } + table.insert(t, 'Required:') for _, v in pairs(modules) do - print(' * ' .. (modules[v] or v)) + table.insert(t, ' * ' .. (modules[v] or v)) end - print('') - error('Missing: ' .. (all[m] or m)) + table.insert(t, '') + table.insert(t, 'Missing: ' .. (all[m] or m)) + error(table.concat(t, '\n')) end end end diff --git a/neural/elytraFly.lua b/neural/elytraFly.lua index eb171ff..776e769 100644 --- a/neural/elytraFly.lua +++ b/neural/elytraFly.lua @@ -11,11 +11,12 @@ local parallel = _G.parallel local STARTUP_FILE = 'usr/autorun/fly.lua' if not modules.launch or not modules.getMetaOwner then - print([[Required: -* Kinetic augment -* Entity sensor -* Introspection module]]) - error('missing required item') + error([[Required: + * Kinetic augment + * Entity sensor + * Introspection module + +Missing required item]]) end if not fs.exists(STARTUP_FILE) then diff --git a/neural/nwm.lua b/neural/nwm.lua index 6100cd0..0df24b8 100644 --- a/neural/nwm.lua +++ b/neural/nwm.lua @@ -8,13 +8,14 @@ local Config = require('opus.config') local Glasses = require('neural.glasses') -local UI = require('opus.ui') local Util = require('opus.util') +local colors = _G.colors local device = _G.device local fs = _G.fs local kernel = _G.kernel local shell = _ENV.shell +local term = _G.term local window = _G.window local config = Config.load('nwm', { session = { } }) @@ -22,10 +23,9 @@ local config = Config.load('nwm', { session = { } }) -- TODO: figure out how to better support scaling local scale = .5 local xs, ys = 6 * scale, 9 * scale -local dragging +local dragging, resizing local canvas = device['plethora:glasses'].canvas() local cw, ch = canvas.getSize() -local opacity = 127 local multishell = Util.shallowCopy(_ENV.multishell) _ENV.multishell = multishell @@ -40,7 +40,6 @@ local events = { } local function hook(e, eventData) - local current = kernel.getFocused() local x = math.floor(eventData[2] / xs) local y = math.floor(eventData[3] / ys) local clicked @@ -61,37 +60,78 @@ local function hook(e, eventData) return end + if resizing then + if e == 'glasses_up' then + resizing.group.remove() + if resizing.dx then + resizing.tab.wmargs.x = resizing.dx + resizing.tab.wmargs.y = resizing.dy + resizing.tab.wmargs.width = resizing.dw + resizing.tab.wmargs.height = resizing.dh + resizing.tab.gwindow.reposition2(resizing.dx, resizing.dy, resizing.dw, resizing.dh) + resizing.tab:resume('term_resize') + + resizing.tab.titleBar.reposition2(resizing.dx, resizing.dy - 1, resizing.dw, 1) + resizing.tab.titleBar:draw(resizing.tab.title) + Config.update('nwm', config) + end + resizing = nil + + elseif e == 'glasses_drag' then + local dx = x - resizing.ax + local dy = y - resizing.ay + + resizing.dx = resizing.tab.wmargs.x + resizing.dy = math.min(resizing.tab.wmargs.y + dy, resizing.tab.wmargs.y + resizing.tab.wmargs.height - 4) + resizing.dw = math.max(resizing.tab.wmargs.width + dx, 8) + resizing.dh = math.max(resizing.tab.wmargs.height - dy, 4) + + resizing.group.setPosition((resizing.dx + 1) * xs, resizing.dy * ys) + resizing.group.setSize(resizing.dw * xs, (resizing.dh + 1) * ys) + end + return + end + for _,tab in ipairs(kernel.routines) do if tab.gwindow then local wx, wy = tab.gwindow.getPosition() local ww, wh = tab.gwindow.getSize() - if x >= wx and x <= wx + ww and y > wy and y < wy + wh then + if x >= wx and x <= wx + ww and y > wy and y <= wy + wh then clicked = tab x = x - wx y = y - wy break - elseif e == 'glasses_click' and x >= wx and x <= wx + ww and y == wy then - if x == wx + ww - 1 then - multishell.terminate(tab.uid) - else - dragging = { tab = tab, ax = x, ay = y, wx = wx, wy = wy } + elseif x >= wx and x <= wx + ww and y == wy then + if e == 'glasses_click' then + if x == wx + ww - 1 then + multishell.terminate(tab.uid) + elseif x == wx + ww - 3 then + local pos = { x = (tab.wmargs.x + 1) * xs, y = tab.wmargs.y * ys } + resizing = { tab = tab, ax = x, ay = y } + resizing.group = canvas.addRectangle(pos.x, pos.y, tab.wmargs.width * xs, (tab.wmargs.height + 1) * ys, 0xF0F0F04F) + else + dragging = { tab = tab, ax = x, ay = y, wx = wx, wy = wy } + end + return + elseif e == 'glasses_scroll' then + tab.wmargs.opacity = Util.clamp(tab.wmargs.opacity - (eventData[1] * 5), 0, 255) + Config.update('nwm', config) + tab.gwindow.setOpacity(tab.wmargs.opacity) end - return end end end if clicked then + local current = kernel.getFocused() if clicked ~= current then clicked.gwindow.raise() + clicked.titleBar.raise() kernel.raise(clicked.uid) end - kernel.event(events[e], { - eventData[1], x, y, clicked.gwindow.side, - }) - + clicked:resume(events[e], eventData[1], x, y) end return true end @@ -103,7 +143,7 @@ function multishell.openTab(env, tab) y = math.random(1, ch - 19 + 1), width = 51, height = 19, - opacity = opacity, + opacity = 192, path = tab.path, args = tab.args, } @@ -125,24 +165,28 @@ function multishell.openTab(env, tab) local wmargs = tab.wmargs - local titleBar = Glasses.create({ - x = wmargs.x, - y = wmargs.y - 1, - height = 1, - width = wmargs.width, - opacity = wmargs.opacity, - }) - titleBar.canvas:clear('yellow') - titleBar.canvas:write(1, 1, ' ' .. fs.getName(tab.path), nil, 'black') - titleBar.canvas:write(wmargs.width - 2, 1, ' x ', nil, 'black') - titleBar.redraw() - if not tab.title and tab.path then tab.title = fs.getName(tab.path):match('([^%.]+)') end tab.hidden = true tab.title = tab.title or 'untitled' + local titleBar = Glasses.create({ + x = wmargs.x, + y = wmargs.y - 1, + height = 1, + width = wmargs.width, + opacity = 160, + }) + titleBar.routine = tab + function titleBar:draw(title) + titleBar.canvas:clear('yellow') + titleBar.canvas:write(1, 1, ' ' .. title, nil, 'black') + titleBar.canvas:write(self.routine.wmargs.width - 4, 1, ' + x ', nil, 'black') + titleBar.redraw() + end + titleBar:draw(tab.title) + local w, h = device.terminal.getSize() tab.window = window.create(device.terminal, 1, 2, w, h - 1, false) tab.gwindow = Glasses.create(wmargs) @@ -163,89 +207,10 @@ function multishell.setTitle(tabId, title) local tab = kernel.find(tabId) if tab then tab.title = title - tab.titleBar.canvas:clear('yellow') - tab.titleBar.canvas:write(1, 1, ' ' .. title, nil, 'black') - tab.titleBar.canvas:write(tab.wmargs.width - 2, 1, ' x ', nil, 'black') - tab.titleBar.redraw() + tab.titleBar:draw(title) end end -UI:setPage(UI.Page { - form = UI.Form { - values = { - x = 1, y = 25, width = 51, height = 19, - opacity = 255, - }, - UI.TextEntry { - formKey = 'run', formLabel = 'Run', required = true, - }, - UI.Slider { - min = 0, max = 255, - formLabel = 'Opacity', formKey = 'opacity', formIndex = 3, - labelWidth = 3, - transform = math.floor, - eventHandler = function(self, event) - if event.type == 'slider_update' then - opacity = event.value - end - return UI.Slider.eventHandler(self, event) - end, - }, - UI.Text { - x = 10, y = 5, - textColor = 'yellow', - value = ' x y' - }, - UI.TextEntry { - x = 10, y = 6, width = 7, limit = 3, - transform = 'number', - formKey = 'x', required = true, - }, - UI.TextEntry { - x = 18, y = 6, width = 7, limit = 4, - transform = 'number', - formKey = 'y', required = true, - }, - UI.Text { - x = 10, y = 8, - textColor = 'yellow', - value = ' width height' - }, - UI.TextEntry { - x = 10, y = 9, width = 7, limit = 4, - transform = 'number', - formKey = 'width', required = true, - }, - UI.TextEntry { - x = 18, y = 9, width = 7, limit = 4, - transform = 'number', - formKey = 'height', required = true, - }, - }, - notification = UI.Notification { }, - eventHandler = function(self, event) - if event.type == 'form_complete' then - local opts = Util.shallowCopy(event.values) - local words = Util.split(opts.run, '(.-) ') - words[1] = shell.resolveProgram(words[1]) - if not words[1] then - self.notification:error('Invalid program') - else - opts.path = 'sys/apps/shell.lua' - opts.args = table.concat(words, ' ') - table.insert(config.session, opts) - Config.update('nwm', config) - multishell.openTab(_ENV, { wmargs = opts }) - self.notification:success('Started program') - end - - elseif event.type == 'form_cancel' then - UI:quit() - end - return UI.Page.eventHandler(self, event) - end, -}) - local hookEvents = Util.keys(events) kernel.hook(hookEvents, hook) @@ -253,6 +218,22 @@ for _,v in pairs(config.session) do multishell.openTab(_ENV, { wmargs = v }) end -UI:start() +term.setBackgroundColor(colors.black) +term.setTextColor(colors.white) +term.clear() +print('Scroll on a titlebar adjusts opacity\n') +print('Run a program') +pcall(function() + while true do + _G.write('> ') + local p = _G.read(nil, nil, shell.complete) + if p and #Util.trim(p) > 0 then + multishell.openTab(_ENV, { + path = 'sys/apps/shell.lua', + args = { p }, + }) + end + end +end) kernel.unhook(hookEvents, hook) -- 2.49.1 From 5a8dbd6589b81ffe96a01b9802eb0eaaacb2fcc8 Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Wed, 13 May 2020 16:59:02 -0700 Subject: [PATCH 09/19] Update exportTask.lua Cheap fix to stop cascading storage updates from eating up all the working time available after failing exports, this needs to be more fleshed out better, if the chest is full, scan the slots for any that match and are not full, stop blindly exporting --- milo/plugins/exportTask.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index c80159e..279573b 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -69,8 +69,8 @@ function ExportTask:cycle(context) for key in pairs(entry.filter) do local items = Milo:getMatches(itemDB:splitKey(key), entry) for _,item in pairs(items) do - if context.storage:export(node, nil, item.count, item) == 0 then - -- TODO: really shouldn't break here as there may be room in other slots + if node.adapter.size() ~= Util.size(node.adapter.list()) and context.storage:export(node, nil, item.count, item) == 0 then + -- TODO: really shouldn't break here as there may be room in other slots (probably not) -- leaving for now for performance reasons break end -- 2.49.1 From 44df3db85f3360798a0e5276b5d54647c4906d72 Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Wed, 13 May 2020 17:14:56 -0700 Subject: [PATCH 10/19] Create furniController.lua (Super)MultiFurnace Controller (did I mention, it's SUPER!?) This app is designed to wrap up to 4 of kepler155c's MultiFurnace (multiFurni) arrays and divide up workload, it functions as a straight drop-in for furni.lua and no other adjustments are required to make it work. Additionally, you get the ability to target any one multiFurni array for smelting when creating the machine recipe in Milo. Further uses for this direct targeting can be limited-scope auto-smelting, using anywhere from 1/2 to 1/4 of your total capacity to auto-smelt, leaving the rest of the cluster available for you when you want it, great for multi-user bases! Setup: Plug this turtle into a modem on your Milo network, and another modem leading to 2-4 turtles running furni.lua (or even furniController.lua for chained setups), configure useSlot4 on line 20, map in Milo and go! --- miloApps/apps/furniController.lua | 184 ++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 miloApps/apps/furniController.lua diff --git a/miloApps/apps/furniController.lua b/miloApps/apps/furniController.lua new file mode 100644 index 0000000..80bc7b6 --- /dev/null +++ b/miloApps/apps/furniController.lua @@ -0,0 +1,184 @@ +-- (Super)MultiFurnace Controller (did I mention, it's SUPER!?) +-- This app is designed to wrap up to 4 of kepler155c's MultiFurnace (multiFurni) arrays and divide up workload, +-- it functions as a straight drop-in for furni.lua and no other adjustments are required to make it work. +-- Additionally, you get the ability to target any one multiFurni array for smelting when creating the machine recipe in Milo +-- Further uses for this direct targeting can be limited-scope auto-smelting, using anywhere from 1/2 to 1/4 of your total +-- capacity to auto-smelt, leaving the rest of the cluster available for you when you want it, great for multi-user bases! + +-- Plug this turtle into a modem on your Milo network, and another modem leading to 2-4 turtles running furni.lua (or even furniController.lua for chained setups) + +-- Slots are as follows: +-- 1: Master Furnace Input +-- 2: Master Furnace Fuel Input +-- 3: Master Furnace Output +-- 4: Optional (Options: "fuel"/"input"/"output"/"" (Default: "" [ignore])) +-- 5-8: Furnace Inputs for up to 4 MultiFurnace arrays +-- 9-12: Furnace Fuels for up to 4 MultiFurnace arrays +-- 13-16: Furnace Outputs for up to 4 MultiFurnace arrays + +-- Only option, slot 4, what to use it for? (Extra) fuel, input, output, [default, ignore] +useSlot4="" -- default:"" [unused, ignore] (REMEMBER: Map this slot accordingly in Milo!) + +--Find modem with -only- turtles attached (these are our furni.lua arrays) +devModem="" +for nDev,modem in ipairs({peripheral.find("modem")}) do + if #modem.getNamesRemote() > 0 then + nTurtles=0 + for nDev,dev in ipairs(modem.getNamesRemote()) do + if modem.getTypeRemote(dev) == "turtle" then nTurtles=nTurtles+1 end + end + if nTurtles==#modem.getNamesRemote() then + devModem=modem + break + end + end +end +if devModem ~= "" then + print("Found turtle-only modem, detected",#devModem.getNamesRemote(),"turtles",(#devModem.getNamesRemote() > 4 and "(Max 4 will be mapped)" or "(All will be mapped)")) +end +devTurtles={} +for nDev,dev in ipairs(devModem.getNamesRemote()) do + if #devTurtles >= 4 then break end + devTurtles[#devTurtles+1]=peripheral.wrap(dev) + print("Mapping",devTurtles[#devTurtles].getLabel(),"("..dev..")","as device",#devTurtles) + devTurtles[#devTurtles].inputSlot=#devTurtles+4 -- Set the input for this device on second row + devTurtles[#devTurtles].fuelSlot=#devTurtles+8 -- Set the fuel for this device on third row + devTurtles[#devTurtles].outputSlot=#devTurtles+12 -- Set the output for this device on fourth row + if devTurtles[#devTurtles].isOn() then + print("Resynchronizing",devTurtles[#devTurtles].getLabel()) + devTurtles[#devTurtles].reboot() + else + print("Powering",devTurtles[#devTurtles].getLabel(),"on") + devTurtles[#devTurtles].turnOn() + end +end + +function manageFuel() + if turtle.getItemCount(2) > 0 then -- Fuel + --print("Fuel found") + splitNum=turtle.getItemCount(2)/#devTurtles + for nDev,dev in ipairs(devTurtles) do + if turtle.select(2) and turtle.getSelectedSlot() == 2 then + turtle.transferTo(dev.fuelSlot,splitNum) + dev.pullItems(devModem.getNameLocal(),dev.fuelSlot,64,2) + end + end + end +end + +turtle.list = function () + local tList={} + for i=1,16 do + local slotData=turtle.getItemDetail(i) -- DWGFJTLR + if slotData ~= nil then + slotData.maxStack=turtle.getItemCount(i) + turtle.getItemSpace(i) + tList[i]=slotData + end + end + return tList +end + +function manageLocalResources() + --print("Input found") + local itemCount=turtle.getItemCount(1)/#devTurtles + if itemCount < 1 then itemCount = 1 end -- Patch for single items fed into master slot + if turtle.getItemCount(1) > 0 then -- Input + for nDev,dev in ipairs(devTurtles) do + local devList=dev.list() + if turtle.select(1) and ((turtle.compareTo(dev.inputSlot) and turtle.getItemSpace(dev.inputSlot) > 0) or turtle.getItemCount(dev.inputSlot) == 0) then -- Move Input + turtle.transferTo(dev.inputSlot,itemCount) + end + if useSlot4 == "input" and turtle.select(4) and ((turtle.compareTo(dev.inputSlot) and turtle.getItemSpace(dev.inputSlot) > 0) or turtle.getItemCount(dev.inputSlot) == 0) then -- Move Input + turtle.transferTo(dev.inputSlot,itemCount) + end --Slot 4 input + end + end + if turtle.select(2) and turtle.getSelectedSlot() == 2 then -- Fuel + for nDev,dev in ipairs(devTurtles) do + local devList=dev.list() + if turtle.compareTo(dev.fuelSlot) or turtle.getItemCount(dev.fuelSlot) == 0 then turtle.transferTo(dev.fuelSlot,64) end -- Move fuel into slot + end + end + if useSlot4 == "fuel" and turtle.select(4) and turtle.getSelectedSlot() == 4 then -- Fuel + for nDev,dev in ipairs(devTurtles) do + local devList=dev.list() + if turtle.compareTo(dev.fuelSlot) or turtle.getItemCount(dev.fuelSlot) == 0 then turtle.transferTo(dev.fuelSlot,64) end -- Move fuel into slot + end + end -- Slot 4 fuel + + for nDev,dev in ipairs(devTurtles) do + local devList=dev.list() + if turtle.getItemCount(3) == 0 and turtle.getItemCount(dev.outputSlot) > 0 then + turtle.select(dev.outputSlot) + turtle.transferTo(3,64) + elseif turtle.getItemCount(dev.outputSlot) > 0 and turtle.select(3) and turtle.compareTo(dev.outputSlot) then -- Move output + --turtle.setStatus("moving") + turtle.select(dev.outputSlot) + turtle.transferTo(3,64) + end + if useSlot4 == "output" then -- Slot 4 output + if turtle.getItemCount(4) == 0 and turtle.getItemCount(dev.outputSlot) > 0 then + turtle.select(dev.outputSlot) + turtle.transferTo(4,64) + elseif turtle.getItemCount(dev.outputSlot) > 0 and turtle.select(4) and turtle.compareTo(dev.outputSlot) then + turtle.select(dev.outputSlot) + turtle.transferTo(4,64) + end + end + end +end + +function manageRemoteResources() + local localList=turtle.list() + for nDev,dev in ipairs(devTurtles) do + local devList=dev.list() + --print(textutils.serialize(devList)) + if devList[2] == nil then + if localList[dev.fuelSlot] ~= nil then + turtle.setStatus("fueling") + dev.pullItems(devModem.getNameLocal(),dev.fuelSlot,64,2) + end + else + if localList[dev.fuelSlot] ~= nil and localList[dev.fuelSlot].name == devList[2].name then + turtle.setStatus("fueling") + dev.pullItems(devModem.getNameLocal(),dev.fuelSlot,64,2) + end + end + if devList[1] == nil then + if localList[dev.inputSlot] ~= nil then + turtle.setStatus("pushing") + dev.pullItems(devModem.getNameLocal(),dev.inputSlot,64,1) + end + else + if localList[dev.inputSlot] ~= nil and localList[dev.inputSlot].name == devList[1].name then + turtle.setStatus("pushing") + dev.pullItems(devModem.getNameLocal(),dev.inputSlot,64,1) + end + end -- Move input + if devList[3] ~= nil then + if localList[dev.outputSlot] == nil then + turtle.setStatus("pulling") + dev.pushItems(devModem.getNameLocal(),3,64,dev.outputSlot) + end + else + if localList[dev.outputSlot] ~= nil then + if devList[3] ~= nil and localList[dev.outputSlot].name == devList[3].name then + turtle.setStatus("pulling") + dev.pushItems(devModem.getNameLocal(),3,64,dev.outputSlot) + end + end + end + end +end + +local lastList={} +while true do -- Main Loop + --manageFuel() + local turtleList=turtle.list() + if turtleList[1]~=nil or turtleList[13]~=nil or turtleList[14]~=nil or turtleList[15]~=nil or turtleList[16]~=nil then + manageLocalResources() + end + manageRemoteResources() + turtle.setStatus("sleeping") + os.sleep(1) +end -- 2.49.1 From fdb2ea31be8568e009009c495af2a0e376bd87de Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Wed, 13 May 2020 23:10:55 -0700 Subject: [PATCH 11/19] Update furniController.lua Cleaned up bad reference naming to avoid confusion. Additionally moved relevant variables to local scope, cleaned up a few other minor things. --- miloApps/apps/furniController.lua | 44 ++++++++++++------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/miloApps/apps/furniController.lua b/miloApps/apps/furniController.lua index 80bc7b6..d6ad9ec 100644 --- a/miloApps/apps/furniController.lua +++ b/miloApps/apps/furniController.lua @@ -1,5 +1,5 @@ -- (Super)MultiFurnace Controller (did I mention, it's SUPER!?) --- This app is designed to wrap up to 4 of kepler155c's MultiFurnace (multiFurni) arrays and divide up workload, +-- This app is designed to wrap up to 4 of kepler155c's furni.lua (multiFurni) arrays and divide up workload, -- it functions as a straight drop-in for furni.lua and no other adjustments are required to make it work. -- Additionally, you get the ability to target any one multiFurni array for smelting when creating the machine recipe in Milo -- Further uses for this direct targeting can be limited-scope auto-smelting, using anywhere from 1/2 to 1/4 of your total @@ -11,18 +11,19 @@ -- 1: Master Furnace Input -- 2: Master Furnace Fuel Input -- 3: Master Furnace Output --- 4: Optional (Options: "fuel"/"input"/"output"/"" (Default: "" [ignore])) --- 5-8: Furnace Inputs for up to 4 MultiFurnace arrays --- 9-12: Furnace Fuels for up to 4 MultiFurnace arrays --- 13-16: Furnace Outputs for up to 4 MultiFurnace arrays +-- 4: Optional (Options: "fuel"/"input"/"output"/nil (Default: nil [ignore])) +-- 5-8: Furnace Inputs for 2 to 4 furni.lua arrays (slots mapped in order ascending, T1_Input=4, T2_Input=5, etc) +-- 9-12: Furnace Fuels for 2 to 4 furni.lua arrays +-- 13-16: Furnace Outputs for 2 to 4 furni.lua arrays --- Only option, slot 4, what to use it for? (Extra) fuel, input, output, [default, ignore] -useSlot4="" -- default:"" [unused, ignore] (REMEMBER: Map this slot accordingly in Milo!) +-- Only user option, slot 4, what to use it for? +local useSlot4=nil ---Find modem with -only- turtles attached (these are our furni.lua arrays) -devModem="" +-- Begin main program code +-- Find modem with -only- turtles attached (these should be our furni/furniController arrays) +local devModem="" for nDev,modem in ipairs({peripheral.find("modem")}) do - if #modem.getNamesRemote() > 0 then + if #modem.getNamesRemote() > 1 then -- We're only looking for 2 or more devices on a network segment, ignore anything less nTurtles=0 for nDev,dev in ipairs(modem.getNamesRemote()) do if modem.getTypeRemote(dev) == "turtle" then nTurtles=nTurtles+1 end @@ -35,8 +36,11 @@ for nDev,modem in ipairs({peripheral.find("modem")}) do end if devModem ~= "" then print("Found turtle-only modem, detected",#devModem.getNamesRemote(),"turtles",(#devModem.getNamesRemote() > 4 and "(Max 4 will be mapped)" or "(All will be mapped)")) +else + print("Did not find a modem with only turtles connected. Please check your networking cables/modems and devices, then try again.") + return -- We don't have a modem, halt end -devTurtles={} +local devTurtles={} for nDev,dev in ipairs(devModem.getNamesRemote()) do if #devTurtles >= 4 then break end devTurtles[#devTurtles+1]=peripheral.wrap(dev) @@ -53,20 +57,7 @@ for nDev,dev in ipairs(devModem.getNamesRemote()) do end end -function manageFuel() - if turtle.getItemCount(2) > 0 then -- Fuel - --print("Fuel found") - splitNum=turtle.getItemCount(2)/#devTurtles - for nDev,dev in ipairs(devTurtles) do - if turtle.select(2) and turtle.getSelectedSlot() == 2 then - turtle.transferTo(dev.fuelSlot,splitNum) - dev.pullItems(devModem.getNameLocal(),dev.fuelSlot,64,2) - end - end - end -end - -turtle.list = function () +local turtle.list = function () -- Supplement a local .list()-like function local tList={} for i=1,16 do local slotData=turtle.getItemDetail(i) -- DWGFJTLR @@ -173,9 +164,8 @@ end local lastList={} while true do -- Main Loop - --manageFuel() local turtleList=turtle.list() - if turtleList[1]~=nil or turtleList[13]~=nil or turtleList[14]~=nil or turtleList[15]~=nil or turtleList[16]~=nil then + if turtleList[1]~=nil or turtleList[13]~=nil or turtleList[14]~=nil or turtleList[15]~=nil or turtleList[16]~=nil or ((useSlot4=="input" or useSlot4=="fuel") and turtleList[4]~=nil) then manageLocalResources() end manageRemoteResources() -- 2.49.1 From 0e2f714c13a301faaeb8fd5c85d25d48e41aa1f5 Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Sat, 16 May 2020 19:36:59 -0700 Subject: [PATCH 12/19] Update exportTask.lua Fleshed out the exportItems function which was blindly firing items into full chests. Made it a little more sensitive, slight increase in average processing time, but no more erroneous hits to export causing perf issues. --- milo/plugins/exportTask.lua | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index 279573b..e59de1e 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -69,10 +69,25 @@ function ExportTask:cycle(context) for key in pairs(entry.filter) do local items = Milo:getMatches(itemDB:splitKey(key), entry) for _,item in pairs(items) do - if node.adapter.size() ~= Util.size(node.adapter.list()) and context.storage:export(node, nil, item.count, item) == 0 then - -- TODO: really shouldn't break here as there may be room in other slots (probably not) - -- leaving for now for performance reasons - break + node.cacheList = node.adapter.list() + if node.adapter.size() ~= Util.size(node.cacheList) then + -- Here we have a storage which has at least 1 unpopulated slot, we can fire'n'forget into this + if context.storage:export(node, nil, item.count, item) == 0 then + -- TODO: really shouldn't break here as there may be room in other slots + -- leaving for now for performance reasons + break + end + else + -- Here we have a storage with all slots occupied, sort through and find open spaces + for iNum,_ in ipairs(node.cacheList) do + local slot = node.adapter.getItemMeta(iNum) + if (slot.name == filterItem.name and slot.count ~= slot.maxCount and + (entry.ignoreDamage or slot.damage == filterItem.damage) and + (entry.ignoreNbtHash or slot.nbtHash == filterItem.nbtHash)) then + -- We found a slot that matches, and is not full, let's export to it! + context.storage:export(node, iNum, slot.maxCount - slot.count, item) + end + end end end end -- 2.49.1 From aeeb8c11fd840c1d2e015911a6553de616304a55 Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Sun, 17 May 2020 16:22:25 -0700 Subject: [PATCH 13/19] Update exportTask.lua Clean up cached .list() after done, accidentally left it in, bloating storage config sizes --- milo/plugins/exportTask.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index e59de1e..766b81b 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -66,10 +66,10 @@ function ExportTask:cycle(context) end local function exportItems() + node.cacheList = node.adapter.list() for key in pairs(entry.filter) do local items = Milo:getMatches(itemDB:splitKey(key), entry) for _,item in pairs(items) do - node.cacheList = node.adapter.list() if node.adapter.size() ~= Util.size(node.cacheList) then -- Here we have a storage which has at least 1 unpopulated slot, we can fire'n'forget into this if context.storage:export(node, nil, item.count, item) == 0 then @@ -91,6 +91,7 @@ function ExportTask:cycle(context) end end end + node.cacheList=nil end if type(entry.slot) == 'number' then exportSingleSlot() -- 2.49.1 From d02f3d36a68e12313b48a2015d9fdbd74ae3ecd2 Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Sun, 17 May 2020 19:44:20 -0700 Subject: [PATCH 14/19] Update exportTask.lua Fixing some logic, make less plethora calls --- milo/plugins/exportTask.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index 766b81b..3c3e3e7 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -66,32 +66,38 @@ function ExportTask:cycle(context) end local function exportItems() + local debugLog="exportItems()" node.cacheList = node.adapter.list() for key in pairs(entry.filter) do local items = Milo:getMatches(itemDB:splitKey(key), entry) for _,item in pairs(items) do if node.adapter.size() ~= Util.size(node.cacheList) then + debugLog=debugLog.." empty slot found" -- Here we have a storage which has at least 1 unpopulated slot, we can fire'n'forget into this if context.storage:export(node, nil, item.count, item) == 0 then + debugLog=debugLog.." failed to export, break" -- TODO: really shouldn't break here as there may be room in other slots -- leaving for now for performance reasons break end else -- Here we have a storage with all slots occupied, sort through and find open spaces + debugLog=debugLog.." no empty slots found, cycling slots" for iNum,_ in ipairs(node.cacheList) do local slot = node.adapter.getItemMeta(iNum) if (slot.name == filterItem.name and slot.count ~= slot.maxCount and (entry.ignoreDamage or slot.damage == filterItem.damage) and (entry.ignoreNbtHash or slot.nbtHash == filterItem.nbtHash)) then + debugLog=debugLog.." found matching slot, exporting" -- We found a slot that matches, and is not full, let's export to it! - context.storage:export(node, iNum, slot.maxCount - slot.count, item) + context.storage:export(node, iNum, math.min(slot.maxCount-slot.count,item.count), item) end end end end end node.cacheList=nil + _G._syslog(debugLog) end if type(entry.slot) == 'number' then exportSingleSlot() -- 2.49.1 From 5b5474a1dcb59e1591a7ef6c991cf62c355a9078 Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Sun, 17 May 2020 19:53:01 -0700 Subject: [PATCH 15/19] Update exportTask.lua --- milo/plugins/exportTask.lua | 6 ------ 1 file changed, 6 deletions(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index 3c3e3e7..9be86b1 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -66,29 +66,24 @@ function ExportTask:cycle(context) end local function exportItems() - local debugLog="exportItems()" node.cacheList = node.adapter.list() for key in pairs(entry.filter) do local items = Milo:getMatches(itemDB:splitKey(key), entry) for _,item in pairs(items) do if node.adapter.size() ~= Util.size(node.cacheList) then - debugLog=debugLog.." empty slot found" -- Here we have a storage which has at least 1 unpopulated slot, we can fire'n'forget into this if context.storage:export(node, nil, item.count, item) == 0 then - debugLog=debugLog.." failed to export, break" -- TODO: really shouldn't break here as there may be room in other slots -- leaving for now for performance reasons break end else -- Here we have a storage with all slots occupied, sort through and find open spaces - debugLog=debugLog.." no empty slots found, cycling slots" for iNum,_ in ipairs(node.cacheList) do local slot = node.adapter.getItemMeta(iNum) if (slot.name == filterItem.name and slot.count ~= slot.maxCount and (entry.ignoreDamage or slot.damage == filterItem.damage) and (entry.ignoreNbtHash or slot.nbtHash == filterItem.nbtHash)) then - debugLog=debugLog.." found matching slot, exporting" -- We found a slot that matches, and is not full, let's export to it! context.storage:export(node, iNum, math.min(slot.maxCount-slot.count,item.count), item) end @@ -97,7 +92,6 @@ function ExportTask:cycle(context) end end node.cacheList=nil - _G._syslog(debugLog) end if type(entry.slot) == 'number' then exportSingleSlot() -- 2.49.1 From 995ca9d486a024931bdbe884b7e2fc892848e0ce Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Mon, 18 May 2020 01:14:28 -0700 Subject: [PATCH 16/19] Update exportTask.lua Last fix, was making a call to Util when it wasn't defined, and left the export function completely dead. Defined correctly, now exporting as expected, whoops. --- milo/plugins/exportTask.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index 9be86b1..ec7f82d 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -1,6 +1,7 @@ local itemDB = require('core.itemDB') local Milo = require('milo') -local Tasks = require('milo.taskRunner') +local Tasks = require('milo.taskRunner') +local Util = require('opus.util') local ExportTask = { name = 'exporter', @@ -19,7 +20,6 @@ function ExportTask:cycle(context) for node in context.storage:filterActive('machine', filter) do tasks:add(function() for _, entry in pairs(node.exports) do - if not entry.filter then -- exports must have a filter -- TODO: validate in exportView -- 2.49.1 From 287340178264ca835d021f9d431a4094588109ca Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Mon, 18 May 2020 03:09:55 -0700 Subject: [PATCH 17/19] Update exportTask.lua So uhh, yeah, the looped getItemMeta calls cost me a LOT of time. Figured out most of the relevant data I wanted was already being provided elsewhere, no extra calls to make, it's as fast as I can make it now. Now it's dependent on the storage optimizations as they stand, this does not speed anything up, just makes it more accurate. --- milo/plugins/exportTask.lua | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index ec7f82d..3c93a6a 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -66,11 +66,12 @@ function ExportTask:cycle(context) end local function exportItems() - node.cacheList = node.adapter.list() + local cache,size={node.adapter.list(),node.adapter.size()} -- Make single calls, not repeat + local cacheSize=Util.size(cache) -- Same, though this call doesn't hurt as bad for key in pairs(entry.filter) do local items = Milo:getMatches(itemDB:splitKey(key), entry) for _,item in pairs(items) do - if node.adapter.size() ~= Util.size(node.cacheList) then + if size ~= cacheSize then -- Here we have a storage which has at least 1 unpopulated slot, we can fire'n'forget into this if context.storage:export(node, nil, item.count, item) == 0 then -- TODO: really shouldn't break here as there may be room in other slots @@ -79,19 +80,21 @@ function ExportTask:cycle(context) end else -- Here we have a storage with all slots occupied, sort through and find open spaces - for iNum,_ in ipairs(node.cacheList) do - local slot = node.adapter.getItemMeta(iNum) - if (slot.name == filterItem.name and slot.count ~= slot.maxCount and - (entry.ignoreDamage or slot.damage == filterItem.damage) and - (entry.ignoreNbtHash or slot.nbtHash == filterItem.nbtHash)) then - -- We found a slot that matches, and is not full, let's export to it! - context.storage:export(node, iNum, math.min(slot.maxCount-slot.count,item.count), item) + for iNum=1,size do + local slot = cache[i] + if slot then + if (slot.name == item.name and slot.count ~= item.maxCount and + (entry.ignoreDamage or slot.damage == item.damage) and + (entry.ignoreNbtHash or slot.nbtHash == item.nbtHash)) then + -- We found a slot that matches, and is not full, let's export to it! + -- Reworked to use item's .maxCount against the existing .list()[slot].count instead of repeat .getItemMeta calls + context.storage:export(node, iNum, math.min(item.maxCount-slot.count,item.count), item) + end end end end end end - node.cacheList=nil end if type(entry.slot) == 'number' then exportSingleSlot() -- 2.49.1 From 37c9988072226d0550cb9115a2864b5162236de7 Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Mon, 18 May 2020 18:18:15 -0700 Subject: [PATCH 18/19] Sync with kepler155c's branch --- milo/plugins/exportTask.lua | 57 +++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index 3c93a6a..c499c7f 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -1,7 +1,6 @@ local itemDB = require('core.itemDB') local Milo = require('milo') -local Tasks = require('milo.taskRunner') -local Util = require('opus.util') +local Tasks = require('milo.taskRunner') local ExportTask = { name = 'exporter', @@ -19,7 +18,11 @@ function ExportTask:cycle(context) for node in context.storage:filterActive('machine', filter) do tasks:add(function() + + local slots + for _, entry in pairs(node.exports) do + if not entry.filter then -- exports must have a filter -- TODO: validate in exportView @@ -66,31 +69,41 @@ function ExportTask:cycle(context) end local function exportItems() - local cache,size={node.adapter.list(),node.adapter.size()} -- Make single calls, not repeat - local cacheSize=Util.size(cache) -- Same, though this call doesn't hurt as bad + local function isPossible(key) + local filterItem = itemDB:get(key) + + if not node.adapter.__size then + node.adapter.__size = node.adapter.size() + end + + -- note that this does not guarantee a match - as + -- we don't have full meta of item in slot + for i = 1, node.adapter.__size do + local slot = slots[i] + if (not slot or slot.name == filterItem.name and + (entry.ignoreDamage or slot.damage == filterItem.damage) and + slot.count < filterItem.maxCount) then + + return true + end + end + end + for key in pairs(entry.filter) do - local items = Milo:getMatches(itemDB:splitKey(key), entry) - for _,item in pairs(items) do - if size ~= cacheSize then - -- Here we have a storage which has at least 1 unpopulated slot, we can fire'n'forget into this + if not slots then + slots = node.adapter.list() + end + if isPossible(key) then + local items = Milo:getMatches(itemDB:splitKey(key), entry) + for _,item in pairs(items) do if context.storage:export(node, nil, item.count, item) == 0 then -- TODO: really shouldn't break here as there may be room in other slots -- leaving for now for performance reasons + break - end - else - -- Here we have a storage with all slots occupied, sort through and find open spaces - for iNum=1,size do - local slot = cache[i] - if slot then - if (slot.name == item.name and slot.count ~= item.maxCount and - (entry.ignoreDamage or slot.damage == item.damage) and - (entry.ignoreNbtHash or slot.nbtHash == item.nbtHash)) then - -- We found a slot that matches, and is not full, let's export to it! - -- Reworked to use item's .maxCount against the existing .list()[slot].count instead of repeat .getItemMeta calls - context.storage:export(node, iNum, math.min(item.maxCount-slot.count,item.count), item) - end - end + else + -- refresh the slots + slots = nil end end end -- 2.49.1 From e0099680d52787a88f89ad2949cf6eaa15e6bcff Mon Sep 17 00:00:00 2001 From: cynagen <43963132+cynagen@users.noreply.github.com> Date: Wed, 20 May 2020 15:46:55 -0700 Subject: [PATCH 19/19] Another resync --- milo/plugins/exportTask.lua | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index c499c7f..3fc6a9f 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -69,20 +69,21 @@ function ExportTask:cycle(context) end local function exportItems() - local function isPossible(key) - local filterItem = itemDB:get(key) - + local function canExport(item) if not node.adapter.__size then node.adapter.__size = node.adapter.size() end - -- note that this does not guarantee a match - as - -- we don't have full meta of item in slot + if not slots then + slots = node.adapter.list() + end + for i = 1, node.adapter.__size do local slot = slots[i] - if (not slot or slot.name == filterItem.name and - (entry.ignoreDamage or slot.damage == filterItem.damage) and - slot.count < filterItem.maxCount) then + if (not slot or slot.name == item.name and + (entry.ignoreDamage or slot.damage == item.damage) and + (entry.ignoreNbtHash or slot.nbtHash == item.nbtHash) and + slot.count < item.maxCount) then return true end @@ -90,21 +91,14 @@ function ExportTask:cycle(context) end for key in pairs(entry.filter) do - if not slots then - slots = node.adapter.list() - end - if isPossible(key) then - local items = Milo:getMatches(itemDB:splitKey(key), entry) - for _,item in pairs(items) do + local items = Milo:getMatches(itemDB:splitKey(key), entry) + for _,item in pairs(items) do + if canExport(item) then if context.storage:export(node, nil, item.count, item) == 0 then - -- TODO: really shouldn't break here as there may be room in other slots - -- leaving for now for performance reasons - break - else - -- refresh the slots - slots = nil end + -- refresh the slots + slots = nil end end end -- 2.49.1