diff --git a/apis/chestAdapter.lua b/apis/chestAdapter.lua index 3688bd1..e23506a 100644 --- a/apis/chestAdapter.lua +++ b/apis/chestAdapter.lua @@ -1,111 +1,152 @@ -local class = require('class') -local Logger = require('logger') +local class = require('class') +local itemDB = require('itemDB') +local Peripheral = require('peripheral') +local Util = require('util') -local ChestProvider = class() - -function ChestProvider:init(args) - - args = args or { } +local ChestAdapter = class() - self.stacks = {} - self.name = 'chest' - self.direction = args.direction or 'up' - self.wrapSide = args.wrapSide or 'bottom' - self.p = peripheral.wrap(self.wrapSide) +local convertNames = { + name = 'id', + damage = 'dmg', + maxCount = 'max_size', + count = 'qty', + displayName = 'display_name', + maxDamage = 'max_dmg', +} +local keys = { + 'damage', + 'displayName', + 'maxCount', + 'maxDamage', + 'name', + 'nbtHash', +} + +-- Strip off color prefix +local function safeString(text) + + local val = text:byte(1) + + if val < 32 or val > 128 then + + local newText = {} + for i = 4, #text do + local val = text:byte(i) + newText[i - 3] = (val > 31 and val < 127) and val or 63 + end + return string.char(unpack(newText)) + end + + return text +end + +local function convertItem(item) + for k,v in pairs(convertNames) do + item[k] = item[v] + item[v] = nil + end + item.displayName = safeString(item.displayName) +end + +function ChestAdapter:init(args) + local defaults = { + name = 'chest', + direction = 'up', + wrapSide = 'bottom', + } + Util.merge(self, defaults) + Util.merge(self, args) + + local chest = Peripheral.getBySide(self.wrapSide) + if not chest then + chest = Peripheral.getByMethod('getAllStacks') + end + if chest then + Util.merge(self, chest) + end end -function ChestProvider:isValid() - return self.p and self.p.getAllStacks +function ChestAdapter:isValid() + return not not self.getAllStacks end -function ChestProvider:refresh() - if self.p then - self.p.condenseItems() - self.stacks = self.p.getAllStacks(false) - local t = { } - for _,s in ipairs(self.stacks) do - local key = s.id .. ':' .. s.dmg - if t[key] and t[key].qty < 64 then - t[key].max_size = t[key].qty - else - t[key] = { - qty = s.qty - } - end - end - for _,s in ipairs(self.stacks) do - local key = s.id .. ':' .. s.dmg - if t[key].max_size then - s.max_size = t[key].qty - else - s.max_size = 64 +function ChestAdapter:refresh(throttle) + return self:listItems(throttle) +end + +-- provide a consolidated list of items +function ChestAdapter:listItems(throttle) + self.cache = { } + + for _,v in pairs(self.getAllStacks(false)) do + convertItem(v) + local key = table.concat({ v.name, v.damage, v.nbtHash }, ':') + + local entry = self.cache[key] + if not entry then + self.cache[key] = v + + local ikey = { v.name, v.damage, v.nbtHash } + if not itemDB:get(ikey) then + local t = { } + for _,k in pairs(keys) do + t[k] = v[k] + end + itemDB:add(ikey, t) end + else + entry.count = entry.count + v.count end end - return self.stacks + itemDB:flush() + return self.cache +end + +function ChestAdapter:getItemInfo(item) + if not self.cache then + self:listItems() + end + local key = table.concat({ item.name, item.damage, item.nbtHash }, ':') + return self.cache[key] end -function ChestProvider:getItemInfo(id, dmg) - local item = { id = id, dmg = dmg, qty = 0, max_size = 64 } - for _,stack in pairs(self.stacks) do - if stack.id == id and stack.dmg == dmg then - item.name = stack.display_name - item.qty = item.qty + stack.qty - item.max_size = stack.max_size - end - end - if item.name then - return item - end -end - -function ChestProvider:craft(id, dmg, qty) +function ChestAdapter:craft(id, dmg, qty) return false end -function ChestProvider:craftItems(items) +function ChestAdapter:craftItems(items) end -function ChestProvider:provide(item, qty, slot) - if self.p then - self.stacks = self.p.getAllStacks(false) - for key,stack in pairs(self.stacks) do - if stack.id == item.id and stack.dmg == item.dmg then - local amount = math.min(qty, stack.qty) - self.p.pushItemIntoSlot(self.direction, key, amount, slot) - qty = qty - amount - if qty <= 0 then - break - end +function ChestAdapter:provide(item, qty, slot, direction) + for key,stack in pairs(self.getAllStacks(false)) do + if stack.id == item.name and + stack.dmg == item.damage and + stack.nbt_hash == item.nbtHash then + + local amount = math.min(qty, stack.qty) + self.pushItemIntoSlot(direction or self.direction, key, amount, slot) + qty = qty - amount + if qty <= 0 then + break end end end end -function ChestProvider:extract(slot, qty) - if self.p then - self.p.pushItem(self.direction, slot, qty) +function ChestAdapter:extract(slot, qty, toSlot) + if toSlot then + self.pushItemIntoSlot(self.direction, slot, qty, toSlot) + else + self.pushItem(self.direction, slot, qty) end end -function ChestProvider:insert(slot, qty) - if self.p then - local s, m = pcall(function() self.p.pullItem(self.direction, slot, qty) end) - if not s and m then - print('chestProvider:pullItem') - print(m) - Logger.log('chestProvider', 'Insert failed, trying again') - sleep(1) - s, m = pcall(function() self.p.pullItem(self.direction, slot, qty) end) - if not s and m then - print('chestProvider:pullItem') - print(m) - Logger.log('chestProvider', 'Insert failed again') - else - Logger.log('chestProvider', 'Insert successful') - end - end +function ChestAdapter:insert(slot, qty) + local s, m = pcall(function() self.pullItem(self.direction, slot, qty) end) + if not s and m then + sleep(1) + pcall(function() self.pullItem(self.direction, slot, qty) end) end end -return ChestProvider +return ChestAdapter diff --git a/apis/chestAdapter18.lua b/apis/chestAdapter18.lua index 4cc2d6b..0dae1ea 100644 --- a/apis/chestAdapter18.lua +++ b/apis/chestAdapter18.lua @@ -16,10 +16,9 @@ local keys = Util.transpose({ function ChestAdapter:init(args) local defaults = { - items = { }, - name = 'chest', + name = 'chest', direction = 'up', - wrapSide = 'bottom', + wrapSide = 'bottom', } Util.merge(self, defaults) Util.merge(self, args) @@ -99,11 +98,11 @@ function ChestAdapter:listItems(throttle) return items end -function ChestAdapter:getItemInfo(name, damage, nbtHash) +function ChestAdapter:getItemInfo(item) if not self.cache then self:listItems() end - local key = table.concat({ name, damage, nbtHash }, ':') + local key = table.concat({ item.name, item.damage, item.nbtHash }, ':') return self.cache[key] end diff --git a/apis/meAdapter.lua b/apis/meAdapter.lua index 6fcd362..d8ec367 100644 --- a/apis/meAdapter.lua +++ b/apis/meAdapter.lua @@ -5,6 +5,49 @@ local Util = require('util') local MEAdapter = class() +local convertNames = { + name = 'id', + damage = 'dmg', + maxCount = 'max_size', + count = 'qty', + displayName = 'display_name', + maxDamage = 'max_dmg', +} +local keys = { + 'damage', + 'displayName', + 'maxCount', + 'maxDamage', + 'name', + 'nbtHash', +} + +-- Strip off color prefix +local function safeString(text) + + local val = text:byte(1) + + if val < 32 or val > 128 then + + local newText = {} + for i = 4, #text do + local val = text:byte(i) + newText[i - 3] = (val > 31 and val < 127) and val or 63 + end + return string.char(unpack(newText)) + end + + return text +end + +local function convertItem(item) + for k,v in pairs(convertNames) do + item[k] = item[v] + item[v] = nil + end + item.displayName = safeString(item.displayName) +end + function MEAdapter:init(args) local defaults = { items = { }, @@ -34,50 +77,8 @@ function MEAdapter:isValid() return self.getAvailableItems and self.getAvailableItems() end --- Strip off color prefix -local function safeString(text) - - local val = text:byte(1) - - if val < 32 or val > 128 then - - local newText = {} - for i = 4, #text do - local val = text:byte(i) - newText[i - 3] = (val > 31 and val < 127) and val or 63 - end - return string.char(unpack(newText)) - end - - return text -end - -local convertNames = { - name = 'id', - damage = 'dmg', - maxCount = 'max_size', - count = 'qty', - displayName = 'display_name', - maxDamage = 'max_dmg', -} - -local function convertItem(item) - for k,v in pairs(convertNames) do - item[k] = item[v] - item[v] = nil - end - item.displayName = safeString(item.displayName) -end - function MEAdapter:refresh() - local keys = { - 'damage', - 'displayName', - 'maxCount', - 'maxDamage', - 'name', - 'nbtHash', - } + self.items = self.getAvailableItems('all') for _,v in pairs(self.items) do Util.merge(v, v.item) @@ -105,7 +106,7 @@ end function MEAdapter:getItemInfo(item) for key,i in pairs(self.items) do if item.name == i.name and item.damage == i.damage and item.nbtHash == i.nbtHash then - return item + return i end end end @@ -143,7 +144,7 @@ function MEAdapter:craft(item, count) dmg = item.damage, nbt_hash = item.nbtHash, }, - qty or 1, + count or 1, cpu ) @@ -207,8 +208,10 @@ function MEAdapter:craftItems(items) if count >= #cpus then break end - if self:craft(item.name, item.damage, item.count) then - count = count + 1 + if not self:isCrafting(item) then + if self:craft(item, item.count) then + count = count + 1 + end end end end diff --git a/apps/builder.lua b/apps/builder.lua index 2b9d968..71bd757 100644 --- a/apps/builder.lua +++ b/apps/builder.lua @@ -7,6 +7,7 @@ requireInjector(getfenv(1)) local Blocks = require('blocks') local class = require('class') local Event = require('event') +local itemDB = require('itemDB') local MEAdapter = require('meAdapter') local Message = require('message') local Point = require('point') @@ -44,9 +45,10 @@ local pistonFacings -- Temp functions until conversion to new adapters is complete local function convertSingleForward(item) + item.displayName = item.display_name item.name = item.id item.damage = item.dmg - item.count = item.count + item.count = item.qty item.maxCount = item.max_size return item end @@ -65,6 +67,7 @@ local function convertSingleBack(item) item.qty = item.count item.max_size = item.maxCount item.display_name = item.displayName + --item.name = item.displayName end return item end @@ -395,7 +398,7 @@ function Builder:getGenericSupplyList(blockIndex) for _,s in pairs(slots) do if s.id then - s.name = blocks.nameDB:getName(s.id, s.dmg) + s.display_name = itemDB:getName({ name = s.id, damage = s.dmg }) end end @@ -476,9 +479,13 @@ function Builder:getSupplies() local t = { } for _,s in ipairs(self.slots) do if s.need > 0 then - local item = convertSingleBack(self.itemAdapter:getItemInfo(s.id, s.dmg)) + local item = convertSingleBack(self.itemAdapter:getItemInfo({ + name = s.id, + damage = s.dmg, + nbtHash = s.nbt_hash, + })) if item then - s.name = item.display_name + s.display_name = item.display_name local qty = math.min(s.need - s.qty, item.qty) @@ -494,7 +501,7 @@ function Builder:getSupplies() s.qty = turtle.getItemCount(s.index) end else - s.name = blocks.nameDB:getName(s.id, s.dmg) + s.display_name = itemDB:getName({ name = s.id, damage = s.dmg }) end end if s.qty < s.need then @@ -1463,10 +1470,10 @@ substitutionPage.menuBar:add({ function substitutionPage.info:draw() local sub = self.parent.sub - local inName = blocks.nameDB:getName(sub.id, sub.dmg) + local inName = itemDB:getName({ name = sub.id, damage = sub.dmg }) local outName = '' if sub.sid then - outName = blocks.nameDB:getName(sub.sid, sub.sdmg) + outName = itemDB:getName({ name = sub.sid, damage = sub.sdmg }) end self:clear() @@ -1513,10 +1520,10 @@ function substitutionPage:eventHandler(event) self.statusBar:draw() elseif event.type == 'grid_select' then - if not blocks.nameDB:lookupName(event.selected.id, event.selected.dmg) then - blocks.nameDB:add({event.selected.id, event.selected.dmg}, event.selected.name) - blocks.nameDB:flush() - end +-- if not item:lookupName(event.selected.id, event.selected.dmg) then +-- blocks.nameDB:add({event.selected.id, event.selected.dmg}, event.selected.name) +-- blocks.nameDB:flush() +-- end self:applySubstitute(event.selected.id, event.selected.dmg) self.info:draw() @@ -1581,15 +1588,15 @@ supplyPage = UI.Page { --{ text = 'Refresh', event = 'refresh', help = 'Refresh inventory' }, { text = 'Continue', event = 'build', help = 'Continue building' }, { text = 'Menu', event = 'menu', help = 'Return to main menu' }, - { text = 'Force Craft', event = 'craft', help = 'Request crafting (again)' }, +-- { text = 'Force Craft', event = 'craft', help = 'Request crafting (again)' }, } }, grid = UI.Grid { columns = { - { heading = 'Name', key = 'name', width = UI.term.width - 7 }, + { heading = 'Name', key = 'display_name', width = UI.term.width - 7 }, { heading = 'Need', key = 'need', width = 4 }, }, - sortColumn = 'name', + sortColumn = 'display_name', y = 3, width = UI.term.width, height = UI.term.height - 3 @@ -1610,10 +1617,11 @@ supplyPage = UI.Page { function supplyPage:eventHandler(event) +--[[ if event.type == 'craft' then local s = self.grid:getSelected() - if Builder.itemAdapter:craft(s.id, s.dmg, s.need-s.qty) then - local name = s.name or '' + if Builder.itemAdapter:craftItems({{ name = s.id, damage = s.dmg, nbtHash = s.nbt_hash }}, s.need-s.qty) then + local name = s.display_name or '' self.statusBar:timedStatus('Requested ' .. s.need-s.qty .. ' ' .. name, 3) else self.statusBar:timedStatus('Unable to craft') @@ -1621,8 +1629,9 @@ function supplyPage:eventHandler(event) elseif event.type == 'refresh' then self:refresh() +]] - elseif event.type == 'build' then + if event.type == 'build' then Builder:build() elseif event.type == 'menu' then @@ -1709,11 +1718,11 @@ listingPage = UI.Page({ }), grid = UI.ScrollingGrid({ columns = { - { heading = 'Name', key = 'name', width = UI.term.width - 14 }, + { heading = 'Name', key = 'display_name', width = UI.term.width - 14 }, { heading = 'Need', key = 'need', width = 5 }, { heading = 'Have', key = 'qty', width = 5 }, }, - sortColumn = 'name', + sortColumn = 'display_name', y = 3, height = UI.term.height-3, help = 'Set a block type or pick a substitute block' @@ -1737,13 +1746,17 @@ function listingPage:eventHandler(event) if event.type == 'craft' then local s = self.grid:getSelected() - local item = convertSingleBack(Builder.itemAdapter:getItemInfo(s.id, s.dmg)) + local item = convertSingleBack(Builder.itemAdapter:getItemInfo({ + name = s.id, + damage = s.dmg, + nbtHash = s.nbt_hash, + })) if item and item.is_craftable then local qty = math.max(0, s.need - item.qty) if item then - Builder.itemAdapter:craft(s.id, s.dmg, qty) - local name = s.name or s.key + Builder.itemAdapter:craftItems({{ name = s.id, damage = s.dmg, nbtHash = s.nbt_hash, count = qty }}) + local name = s.display_name or s.id self.statusBar:timedStatus('Requested ' .. qty .. ' ' .. name, 3) end else @@ -1801,27 +1814,31 @@ function listingPage:refresh(throttle) for _,b in pairs(supplyList) do if b.need > 0 then - local item = convertSingleBack(Builder.itemAdapter:getItemInfo(b.id, b.dmg)) + local item = convertSingleBack(Builder.itemAdapter:getItemInfo({ + name = b.id, + damage = b.dmg, + nbtHash = b.nbt_hash, + })) if item then - local block = blocks.blockDB:lookup(b.id, b.dmg) - if not block then - blocks.nameDB:add({b.id, b.dmg}, item.display_name) - elseif not block.name and item.display_name then - blocks.nameDB:add({b.id, b.dmg}, item.display_name) - end - b.name = item.display_name +-- local block = blocks.blockDB:lookup(b.id, b.dmg) +-- if not block then +-- blocks.nameDB:add({b.id, b.dmg}, item.display_name) +-- elseif not block.name and item.display_name then +-- blocks.nameDB:add({b.id, b.dmg}, item.display_name) +-- end + b.display_name = item.display_name b.qty = item.qty b.is_craftable = item.is_craftable else - b.name = blocks.nameDB:getName(b.id, b.dmg) + b.display_name = itemDB:getName({ name = b.id, damage = b.dmg }) end end if throttle then throttle() end end - blocks.nameDB:flush() + --blocks.nameDB:flush() if self.fullList then self.grid:setValues(supplyList) diff --git a/apps/supplier.lua b/apps/supplier.lua index 042de28..779c049 100644 --- a/apps/supplier.lua +++ b/apps/supplier.lua @@ -139,7 +139,7 @@ function Builder:getSupplies() local t = { } for _,s in ipairs(self.slots) do if s.need > 0 then - local item = Builder.itemProvider:getItemInfo(s.id, s.dmg) + local item = Builder.itemProvider:getItemInfo(s) if item then if item.name then s.name = item.name