From 2e39a66f8f2273fbf63d2b7c9eec9ff8076cb8af Mon Sep 17 00:00:00 2001 From: scmcgowen <34895975+scmcgowen@users.noreply.github.com> Date: Fri, 23 Jun 2023 20:10:01 -0700 Subject: [PATCH 1/6] Update crafter.lua to fix a typo --- clients/crafter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/crafter.lua b/clients/crafter.lua index b041b81..085a709 100644 --- a/clients/crafter.lua +++ b/clients/crafter.lua @@ -372,7 +372,7 @@ interfaceLUT = { return end changeState(STATES.BUSY) - print("Too add a crafting recipe, place the recipe in the turtle's inventory.") + print("To add a crafting recipe, place the recipe in the turtle's inventory.") print("Then enter 1 for shaped, 2 for unshaped, or anything else to cancel") local shapeSelection = read() if shapeSelection == "1" then From c29a05bfd0b7bf6cc40ff05b141818b559efd6f6 Mon Sep 17 00:00:00 2001 From: betweentheframes <119465870+throughthefog@users.noreply.github.com> Date: Fri, 21 Jul 2023 15:17:14 -0400 Subject: [PATCH 2/6] Add the websocket setup from terminal.lua to usageMonitor --- clients/usageMonitor.lua | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/clients/usageMonitor.lua b/clients/usageMonitor.lua index 73fe71a..8bae6f6 100644 --- a/clients/usageMonitor.lua +++ b/clients/usageMonitor.lua @@ -6,15 +6,41 @@ if not settings.get("misc.monitor") then settings.set("misc.monitor", monitorSide) settings.save() end +if settings.get("misc.wireless") == nil then + settings.define("misc.wireless",{ description = "Should this monitor be in wireless mode? (Use websocket)", type = "boolean"}) + settings.define("misc.websocketURL",{ description = "URL of the websocket to use for wireless communication", type = "string" }) + print("Should this operate in wireless mode?") + print("Wireless mode would be for connecting without a modem.") + print("Otherwise, you will need to connect to a modem on the MISC network.") + print("y/n? ") + local choice + while choice ~= 'y' and choice ~= 'n' do + choice = read() + end + wirelessMode = choice == 'y' + settings.set("misc.wireless", wirelessMode) + if wirelessMode then + print("Enter the URL of the websocket relay service you would like to use.") + settings.set("misc.websocketURL", read()) + end + settings.save() +end local textScale = 0.5 settings.load() monitorSide = settings.get("misc.monitor") local monitor = assert(peripheral.wrap(monitorSide), "Invalid monitor") -local lib = require("modemLib") -local modem = peripheral.getName(peripheral.find("modem")) -lib.connect(modem) +local lib +if not settings.get("misc.wireless") + lib = require("modemLib") + local modem = peripheral.getName(peripheral.find("modem")) + lib.connect(modem) +else + lib = require("websocketLib") + local websocket = settings.get("misc.websocketURL") + lib.connect(websocket) +end local labelFG = colors.black local labelBG = colors.white From dd6c3af0e2d92865dca5ff9f3e6604d5826e4eb1 Mon Sep 17 00:00:00 2001 From: betweentheframes <119465870+throughthefog@users.noreply.github.com> Date: Fri, 21 Jul 2023 15:20:38 -0400 Subject: [PATCH 3/6] Add websocket terminal to installer --- installer.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/installer.lua b/installer.lua index 0f45ae1..6ac0076 100644 --- a/installer.lua +++ b/installer.lua @@ -105,6 +105,7 @@ local introspectionTermInstall = { } } + local crafterInstall = { name = "Crafter Turtle", files = { @@ -120,12 +121,21 @@ local monitorInstall = { } } +local introspectionMonInstall = { + name = "Usage Monitor (Introspection)", + files = { + ["startup.lua"] = fromRepository "clients/usageMonitor.lua", + ["websocketLib.lua"] = fromRepository "clients/websocketLib.lua" + } +} + local clientInstallOptions = { name = "Client installation options", t = terminalInstall, i = introspectionTermInstall, c = crafterInstall, m = monitorInstall, + w = introspectionMonInstall, } local installOptions = { From 35787d44e672aa5b92e0463165a22c58cf26fe6c Mon Sep 17 00:00:00 2001 From: betweentheframes <119465870+throughthefog@users.noreply.github.com> Date: Sat, 22 Jul 2023 18:42:46 -0400 Subject: [PATCH 4/6] Add suggested changes to usageMonitor.lua --- clients/usageMonitor.lua | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/clients/usageMonitor.lua b/clients/usageMonitor.lua index 8bae6f6..51b8ad0 100644 --- a/clients/usageMonitor.lua +++ b/clients/usageMonitor.lua @@ -6,23 +6,11 @@ if not settings.get("misc.monitor") then settings.set("misc.monitor", monitorSide) settings.save() end -if settings.get("misc.wireless") == nil then - settings.define("misc.wireless",{ description = "Should this monitor be in wireless mode? (Use websocket)", type = "boolean"}) +local wirelessMode = fs.exists("websocketLib.lua") +if wirelessMode and not settings.get("misc.websocketURL") then settings.define("misc.websocketURL",{ description = "URL of the websocket to use for wireless communication", type = "string" }) - print("Should this operate in wireless mode?") - print("Wireless mode would be for connecting without a modem.") - print("Otherwise, you will need to connect to a modem on the MISC network.") - print("y/n? ") - local choice - while choice ~= 'y' and choice ~= 'n' do - choice = read() - end - wirelessMode = choice == 'y' - settings.set("misc.wireless", wirelessMode) - if wirelessMode then - print("Enter the URL of the websocket relay service you would like to use.") - settings.set("misc.websocketURL", read()) - end + print("Enter the URL of the websocket relay service you would like to use.") + settings.set("misc.websocketURL", read()) settings.save() end local textScale = 0.5 From 89a82a4c124eea4c74e33b4fb313c014981dd726 Mon Sep 17 00:00:00 2001 From: betweentheframes <119465870+throughthefog@users.noreply.github.com> Date: Sat, 22 Jul 2023 18:43:46 -0400 Subject: [PATCH 5/6] forgot something --- clients/usageMonitor.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/usageMonitor.lua b/clients/usageMonitor.lua index 51b8ad0..190049a 100644 --- a/clients/usageMonitor.lua +++ b/clients/usageMonitor.lua @@ -20,7 +20,7 @@ monitorSide = settings.get("misc.monitor") local monitor = assert(peripheral.wrap(monitorSide), "Invalid monitor") local lib -if not settings.get("misc.wireless") +if not wirelessMode then lib = require("modemLib") local modem = peripheral.getName(peripheral.find("modem")) lib.connect(modem) From a2b7fbf6c0b86a86cae1e0df693d493716e1c51b Mon Sep 17 00:00:00 2001 From: Mason Gulu Date: Sat, 17 Feb 2024 12:28:28 -0500 Subject: [PATCH 6/6] Turtle inventory event debounce + better controls --- clients/terminal.lua | 135 ++++++++++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 45 deletions(-) diff --git a/clients/terminal.lua b/clients/terminal.lua index 44c3c1f..7e4a725 100644 --- a/clients/terminal.lua +++ b/clients/terminal.lua @@ -127,9 +127,9 @@ if not turtleMode then pollFrequency = 3 end -local function eventTurtleInventory() +local function processTurtleInventory() while true do - os.pullEvent("turtle_inventory") + os.pullEvent("do_turtle_transfers") for i = importStart, importEnd do if turtle.getItemDetail(i) then lib.pullItems(true, inventory, i, nil, nil, nil, { optimal = false }) @@ -147,6 +147,22 @@ local function eventTurtleInventory() end end +local function debounceTurtleInventory() + local dropExportTimer + while true do + local e, id = os.pullEvent() + if e == "turtle_inventory" then + if dropExportTimer then + os.cancelTimer(dropExportTimer) + end + dropExportTimer = os.startTimer(0.1) + elseif e == "timer" and id == dropExportTimer then + dropExportTimer = nil + os.queueEvent("do_turtle_transfers") + end + end +end + local function inventoryPoll() local slotActive = false local slotActiveTicks = 0 @@ -503,14 +519,15 @@ local filter = "" ---Handle creating and drawing a searchable menu ---@param drawer fun(filter: string, selected: integer, sifted: any[]) ---@param listProvider fun(): any[] ----@param onSelect fun(selected: any) +---@param onSelect fun(selected: any, index: integer) ---@param event nil|fun(e: any[]): boolean? ---@param sort nil|fun(a: any, b: any): boolean ---@param match nil|fun(val: any, pattern: string): boolean ---@param tab function? mode to switch to upon pushing tab -local function searchableMenu(drawer, listProvider, onSelect, event, sort, match, tab) +---@param selected integer? +local function searchableMenu(drawer, listProvider, onSelect, event, sort, match, tab, selected) local sifted = filterList(listProvider(), filter, sort, match) - local selected = 1 + selected = selected or 1 local controlHeld = false while true do draw(drawer, filter, selected, sifted) @@ -535,7 +552,7 @@ local function searchableMenu(drawer, listProvider, onSelect, event, sort, match selected = math.min(selected + 1, #sifted) elseif isEnter(key) then if selected > 0 and sifted[selected] then - return onSelect(sifted[selected]) + return onSelect(sifted[selected], selected) end elseif key == keys.tab and tab then return tab() @@ -553,7 +570,7 @@ local function searchableMenu(drawer, listProvider, onSelect, event, sort, match elseif e[1] == "mouse_click" and e[4] > 3 then selected = math.max(math.min(getFirstItemOnScreen(selected, sifted) + e[4] - 4, #sifted), 1) if sifted[selected] then - return onSelect(sifted[selected]) + return onSelect(sifted[selected], selected) end elseif e[1] == "mouse_click" then local nm = handleClicks(e[3], e[4]) @@ -566,7 +583,7 @@ local function searchableMenu(drawer, listProvider, onSelect, event, sort, match end end - +local search_selected = 1 function SEARCH() local list = lib.list() mode = "SEARCH" @@ -588,7 +605,8 @@ function SEARCH() return a.name < b.name end - local onSelect = function(selected) + local onSelect = function(selected, index) + search_selected = index return INFO(selected) end @@ -599,7 +617,7 @@ function SEARCH() end end - return searchableMenu(drawer, function() return list end, onSelect, event, sort, match, CRAFT) + return searchableMenu(drawer, function() return list end, onSelect, event, sort, match, CRAFT, search_selected) end function CRAFT() @@ -619,45 +637,71 @@ function CRAFT() return searchableMenu(drawer, function() return craftables end, onSelect, nil, nil, nil, CONFIG) end -function INFO(item) - mode = "INFO" - local itemAmount = tostring(math.min(item.maxCount, item.count)) +---Read some number from the user +---@param input number|string +---@return number +local function scroll_read(input) + ---@type string + input = tostring(input) + local shiftHeld = false + local x, y = term.getCursorPos() while true do - draw(function() - setColors(headerFg, headerBg) - clearLine(2) - text(1, 2, ("%u x %s"):format(item.count, item.displayName)) - setColors(mainFg, mainBg) - text(1, 3, item.name) - text(1, 4, item.nbt) - if item.enchantments then - text(1, 5, "Enchantments") - for k, v in ipairs(item.enchantments) do - text(1, 5 + k, v.displayName or v.name) - end - end - text(1, h, ("Withdraw: %s"):format(itemAmount)) - display.setCursorBlink(true) - display.setCursorPos(itemAmount:len() + 11, h) - end) - local e = { os.pullEvent() } - if e[1] == "char" then - local ch = e[2] - if ch >= '0' and ch <= '9' then - itemAmount = itemAmount .. ch + term.setCursorPos(x, y) + term.write((" "):rep(#input + 1)) + term.setCursorPos(x, y) + term.write(input) + local e, char = os.pullEvent() + if e == "char" and tonumber(char) then + input = input .. char + elseif e == "key" then + if char == keys.backspace then + input = input:sub(1, -2) + elseif char == keys.enter then + return tonumber(input) or 0 + elseif char == keys.leftShift then + shiftHeld = true end - elseif e[1] == "key" then - local key = e[2] - if key == keys.backspace then - itemAmount = itemAmount:sub(1, -2) - elseif isEnter(key) then - requestItem(false, item, tonumber(itemAmount or 0)) - return SEARCH() + elseif e == "key_up" and char == keys.leftShift then + shiftHeld = false + elseif e == "mouse_scroll" then + local scrollAmount = ((shiftHeld and 8) or 1) * -char + local newValue = math.max(scrollAmount + (tonumber(input) or 0), 0) + newValue = math.ceil(newValue / scrollAmount) * scrollAmount + input = tostring(newValue) + elseif e == "mouse_click" then + if char == 1 then + return tonumber(input) or 0 + elseif char == 2 then + return 0 end end end end +function INFO(item) + mode = "INFO" + local itemAmount = math.min(item.maxCount, item.count) + draw(function() + setColors(headerFg, headerBg) + clearLine(2) + text(1, 2, ("%u x %s"):format(item.count, item.displayName)) + setColors(mainFg, mainBg) + text(1, 3, item.name) + text(1, 4, item.nbt) + if item.enchantments then + text(1, 5, "Enchantments") + for k, v in ipairs(item.enchantments) do + text(1, 5 + k, v.displayName or v.name) + end + end + text(1, h, "Withdraw: ") + display.setCursorBlink(true) + end) + itemAmount = scroll_read(itemAmount) + requestItem(false, item, tonumber(itemAmount or 0)) + return SEARCH() +end + function REQUEST(item) mode = "REQUEST" if not item then @@ -673,8 +717,8 @@ function REQUEST(item) display.setCursorPos(1, 3) display.clearLine() end) - local input = read() - if input == "" then + local input = scroll_read(1) + if input == 0 then return CRAFT() end local num_input = tonumber(input) @@ -1136,7 +1180,8 @@ modeLookup = { SEARCH = SEARCH, CRAFT = CRAFT, CONFIG = CONFIG, SYSINFO = SYSINF local funcs = { lib.subscribe, SEARCH } if turtleMode then - funcs[#funcs + 1] = eventTurtleInventory + funcs[#funcs + 1] = debounceTurtleInventory + funcs[#funcs + 1] = processTurtleInventory else funcs[#funcs + 1] = inventoryPoll end