diff --git a/OpenOS/usr/bin/items.lua b/OpenOS/usr/bin/items.lua new file mode 100644 index 0000000..db08274 --- /dev/null +++ b/OpenOS/usr/bin/items.lua @@ -0,0 +1,140 @@ +local inv = require "inv" +local event = require "event" +local sides = require "sides" + +local searchterm = "" +local output = nil +local ci,si = 1,1 +local run = true + +local function search() + io.write("\n\27[2KSearch: ") + searchterm = io.read() +end +local function setOutput() + io.write("\n\27[2KOutput side:") + local in = io.read() + output = tonumber(in) or sides[in] +end + +local function extract(res) + local slot,item = res[1], res[2] + io.write(string.format("\nExtracting %s; Count [64] or x to exit? ",item.label)) + local count = io.read() + if count == "x" then return false end + count=tonumber(count) or 64 + inv.extractItem(slot,count) +end + +local function popup(str,title) + if title then + title=string.format("[%s]",title or "") + else + title = "" + end + local width, height, content = 0, 0, {} + for line in str:gmatch("[^\n]*") do + height = height + 1 + width = math.max(width,line:len()) + content[#content+1] = line + end + if width < 1 or height < 1 then return false end + local startx,starty = (40-(width//2))-2, (12-(height//2))-2 + io.write(string.format("\27[%d;%dH╒═%s%s╕",starty,startx,title,("═"):rep((width+1)-title:len()))) + for k,v in pairs(content) do + io.write(string.format("\27[%d;%dH│ %s%s │",starty+k,startx,v,(" "):rep(width-v:len()))) + end + io.write(string.format("\27[%d;%dH┕%s┙",starty+1+#content,startx,("━"):rep(width+2))) +end + +local function info(item) + local s = string.format("\n%s (%s)\nCount: %d\n",item.label,item.name,item.size) + if item.aspects then + s=s.."Aspects: " + for k,v in pairs(item.aspects) do + s=string.format("%s\n - %d x %s",s,v,k) + end + end + s=s.."\n\nPress any key." + popup(s,item.label or item.name) + event.pull("key_down") +end + +local function help() + popup("\n[Tab] Search\n[Enter] Extract Items\n[i] Item Information\n[r] Refresh\n[o] Set output\n\nPress any key.","Key bindings") + event.pull("key_down") +end + +local function draw(sr, ci, used, size) + io.write("\27[2J\27[H") + for i = si, si+22 do + if sr[i] then + item = sr[i][2] + pt = " " + if ci == i then + pt = ">" + end +-- print(string.format("%s %s (%s - %d)",pt,item.label, item.name, item.size):sub(1,79)) + print(string.format("%s %s (%d - %dx%d + %d)",pt,item.label, item.size, math.floor(item.size/item.maxSize),item.maxSize,item.size%item.maxSize):sub(1,79)) + end + end + io.write("\27[25;62HPress [H] for help.") +-- io.write(string.format("\27[24;1H(%d/%d) [Tab] Search [Enter] Extract [i] Information [r] Refresh",used,size)) + io.write(string.format("\27[24;1H(%d/%d) %s",used,size-1,searchterm)) +end + +while run do + local sr, used, size = inv.search(searchterm) + ci = 1 + while true do + --[[ + if ci > math.min(#sr,23) then + ci = math.min(#sr,23) + elseif ci < 1 then + ci = 1 + end + ]]-- + if ci > #sr then + ci = #sr + elseif ci < 1 then + ci = 1 + end + if ci > math.min(si + 20,#sr) then + si = si + 5 + elseif ci < si + 2 then + si = si - 5 + end + if si < 1 then + si = 1 + elseif si > #sr then + si = sr - 23 + end + draw(sr,ci,used,size) + local _,_,ch,co = event.pull("key_down") + ch=string.char(ch) + if co == 208 then -- down + ci = ci + 1 + elseif co == 200 then -- up + ci = ci - 1 + elseif co == 28 then -- enter + extract(sr[ci]) + break + elseif co == 15 then -- tab + search() + break + elseif ch == "i" then + info(sr[ci][2]) + elseif ch == "h" then + help() + elseif ch == "r" then + popup("Refreshing index...") + inv.inputItems() + break + elseif ch == "o" then + setOutput() + elseif ch == "q" then + run = false + break + end + end +end diff --git a/OpenOS/usr/lib/inv.lua b/OpenOS/usr/lib/inv.lua new file mode 100644 index 0000000..020975b --- /dev/null +++ b/OpenOS/usr/lib/inv.lua @@ -0,0 +1,96 @@ +local component = require "component" +local computer = require "computer" +local sides = require "sides" +local invc = component.transposer + +local inv = {} + +inv.drawer = sides.top +inv.input=sides.north +inv.output=sides.south + +inv.cache = {} +inv.size = 0 +inv.cacheTime = -1000 +inv.cacheInvalid = false + +function inv.index() -- refresh the index of items in the storage system + inv.size = invc.getInventorySize(inv.drawer) + inv.cache = {} + for k,v in pairs(invc.getAllStacks(inv.drawer).getAll()) do + if v.name ~= "minecraft:air" then + inv.cache[#inv.cache+1] = {k,v} + end + end + inv.cacheTime = computer.uptime() + inv.cacheInvalid = false +end + +function inv.cacheInvalidation() -- re-index only if necessary + if computer.uptime() > inv.cacheTime + 300 or inv.cacheInvalid then + inv.index() + inv.loadLists() + end +end + +function inv.search(str) -- search names and labels for *str* + inv.cacheInvalidation() + str = string.lower(str or "") + local rt = {} + for k,v in pairs(inv.cache) do + item = v[2] + item.label = item.label or "" + if item.name:match(str) or item.label:lower():match(str) then + rt[#rt+1] = v + end + end + return rt,#inv.cache,inv.size +end + +function inv.inputItems() -- pull items into the storage system from the input box + local counter = 0 + local imap = invc.getAllStacks(inv.input).getAll() + for i = 1, invc.getInventorySize(inv.input) do + local item = imap[i] + if item.name ~= "minecraft:air" then + if item.maxSize < 2 then + invc.transferItem(inv.input,inv.output,64,i) + else + counter=counter+invc.transferItem(inv.input,inv.drawer,64,i) + end + end + end + if counter > 0 then + inv.cacheInvalid = true + end +end + +function inv.extractItem(slot,count,output) + local tcount = 0 + local item = invc.getStackInSlot(inv.drawer,slot) + if item.size <= count then + inv.cacheInvalid = true + end + count=math.min(count,item.size) + local transferred = 0 + repeat + transferred = invc.transferItem(inv.drawer,output or inv.output,count - tcount,slot) + tcount = tcount + transferred + for k,v in pairs(inv.cache) do + if v[1] == slot then + inv.cache[k][2].size = inv.cache[k][2].size - transferred or 0 + if inv.cache[k][2].size < 1 then + inv.cacheInvalid = true + break + end + end + end + io.write(tcount.." ") + until tcount >= count + return tcount +end + +inv.loadLists() +inv.index() + +return inv