From a19960959b08f0ebc6ba32db23fb6ac6a09f1d7c Mon Sep 17 00:00:00 2001 From: kepler155c Date: Tue, 23 Oct 2018 03:04:34 -0400 Subject: [PATCH] lora wip --- inventoryManager/apis/lora.lua | 370 ++++++++++++++++++ inventoryManager/apis/lora/lora.lua | 334 ---------------- inventoryManager/apis/lora/tasks.lua | 12 - inventoryManager/apis/networkedAdapter18.lua | 16 +- inventoryManager/apis/turtle/craft.lua | 52 ++- inventoryManager/core/machines.lua | 197 ++++++++++ inventoryManager/inventoryManager.lua | 31 +- inventoryManager/plugins/autocraftTask.lua | 6 +- .../plugins/{craft.lua => demandCraft.lua} | 52 ++- inventoryManager/plugins/exportTask.lua | 13 +- inventoryManager/plugins/exportView.lua | 121 ++++++ inventoryManager/plugins/importTask.lua | 4 +- inventoryManager/plugins/importView.lua | 56 +++ inventoryManager/plugins/inputChestTask.lua | 40 +- inventoryManager/plugins/item.lua | 8 +- inventoryManager/plugins/jobList.lua | 2 +- inventoryManager/plugins/learn.lua | 2 +- inventoryManager/plugins/limitTask.lua | 45 ++- inventoryManager/plugins/listing.lua | 56 +-- inventoryManager/plugins/machines.lua | 152 ------- inventoryManager/plugins/replenishTask.lua | 3 +- inventoryManager/plugins/storageView.lua | 44 +++ 22 files changed, 965 insertions(+), 651 deletions(-) create mode 100644 inventoryManager/apis/lora.lua delete mode 100644 inventoryManager/apis/lora/lora.lua delete mode 100644 inventoryManager/apis/lora/tasks.lua create mode 100644 inventoryManager/core/machines.lua rename inventoryManager/plugins/{craft.lua => demandCraft.lua} (76%) create mode 100644 inventoryManager/plugins/exportView.lua create mode 100644 inventoryManager/plugins/importView.lua delete mode 100644 inventoryManager/plugins/machines.lua create mode 100644 inventoryManager/plugins/storageView.lua diff --git a/inventoryManager/apis/lora.lua b/inventoryManager/apis/lora.lua new file mode 100644 index 0000000..d866d48 --- /dev/null +++ b/inventoryManager/apis/lora.lua @@ -0,0 +1,370 @@ +local Craft = require('turtle.craft') +local itemDB = require('itemDB') +local Util = require('util') + +local os = _G.os +local term = _G.term +local turtle = _G.turtle + +local Lora = { + RECIPES_FILE = 'usr/config/recipes.db', + RESOURCE_FILE = 'usr/config/resources.db', + + STATUS_INFO = 'info', + STATUS_WARNING = 'warning', + STATUS_ERROR = 'error', + + tasks = { }, + craftingStatus = { }, +} + +function Lora:init(context) + self.context = context +end + +function Lora:getContext() + return self.context +end + +function Lora:pauseCrafting() + self.craftingPaused = true +end + +function Lora:resumeCrafting() + self.craftingPaused = false +end + +function Lora:isCraftingPaused() + return self.craftingPaused +end + +function Lora:uniqueKey(item) + return table.concat({ item.name, item.damage, item.nbtHash }, ':') +end + +function Lora:getCraftingStatus() + return self.craftingStatus +end + +function Lora:resetCraftingStatus() + self.craftingStatus = { } + self.context.inventoryAdapter.activity = { } +end + +function Lora:updateCraftingStatus(list) + for k,v in pairs(list) do + self.craftingStatus[k] = v + end +end + +function Lora:registerTask(task) + table.insert(self.tasks, task) +end + +function Lora:showError(msg) + term.clear() + self.context.jobList:showError() + print(msg) + print('rebooting in 5 secs') + os.sleep(5) + os.reboot() +end + +function Lora:getItem(items, inItem, ignoreDamage, ignoreNbtHash) + for _,item in pairs(items) do + if item.name == inItem.name and + (ignoreDamage or item.damage == inItem.damage) and + (ignoreNbtHash or item.nbtHash == inItem.nbtHash) then + return item + end + end +end + +function Lora:getItemWithQty(res, ignoreDamage, ignoreNbtHash) + local items = self:listItems() + local item = self:getItem(items, res, ignoreDamage, ignoreNbtHash) + + if item and (ignoreDamage or ignoreNbtHash) then + local count = 0 + + for _,v in pairs(items) do + if item.name == v.name and + (ignoreDamage or item.damage == v.damage) and + (ignoreNbtHash or item.nbtHash == v.nbtHash) then + count = count + v.count + end + end + item.count = count + end + + return item +end + +function Lora:clearGrid() + local function clear() + turtle.eachFilledSlot(function(slot) + self.context.inventoryAdapter:insert(slot.index, slot.count, nil, slot) + end) + + for i = 1, 16 do + if turtle.getItemCount(i) ~= 0 then + return false + end + end + return true + end + return clear() or clear() +end + +function Lora:eject(item, qty) + local s, m = pcall(function() + self.context.inventoryAdapter:provide(item, qty) + turtle.emptyInventory() + end) + if not s and m then + debug(m) + end +end + +function Lora:mergeResources(t) + for _,v in pairs(self.context.resources) do + local item = Lora:getItem(t, v) + if item then + Util.merge(item, v) + else + item = Util.shallowCopy(v) + item.count = 0 + table.insert(t, item) + end + end + + for k in pairs(Craft.recipes) do + local v = itemDB:splitKey(k) + local item = Lora:getItem(t, v) + if not item then + item = Util.shallowCopy(v) + item.count = 0 + table.insert(t, item) + end + item.has_recipe = true + end + + for _,v in pairs(t) do + if not v.displayName then + v.displayName = itemDB:getName(v) + end + v.lname = v.displayName:lower() + end +end + +function Lora:saveResources() + local t = { } + + for k,v in pairs(self.context.resources) do + v = Util.shallowCopy(v) + local keys = Util.transpose({ 'auto', 'low', 'limit', + 'ignoreDamage', 'ignoreNbtHash', + 'rsControl', 'rsDevice', 'rsSide' }) + + for _,key in pairs(Util.keys(v)) do + if not keys[key] then + v[key] = nil + end + end + if not Util.empty(v) then + t[k] = v + end + end + + Util.writeTable(Lora.RESOURCE_FILE, t) +end + +-- Return a list of everything in the system +function Lora:listItems() + for _ = 1, 5 do + self.items = self.context.inventoryAdapter:listItems() + if self.items then + break + end +-- jobList:showError('Error - retrying in 3 seconds') + os.sleep(3) + end + if not self.items then + self:showError('Error - rebooting in 5 seconds') + end + + return self.items +end + +function Lora:addCraftingRequest(item, craftList, count) + local key = self:uniqueKey(item) + local request = craftList[key] + if not craftList[key] then + request = { name = item.name, damage = item.damage, nbtHash = item.nbtHash, count = 0 } + request.displayName = itemDB:getName(request) + craftList[key] = request + end + request.count = request.count + count + return request +end + +-- Craft +function Lora:craftItem(recipe, items, originalItem, craftList, count) + local missing = { } + local toCraft = Craft.getCraftableAmount(recipe, count, items, missing) + if missing.name then + originalItem.status = string.format('%s missing', itemDB:getName(missing.name)) + originalItem.statusCode = self.STATUS_WARNING + end + + local crafted = 0 + + if toCraft > 0 then + crafted = Craft.craftRecipe(recipe, toCraft, self.context.inventoryAdapter) + self:clearGrid() + items = self:listItems() + count = count - crafted + end + + if count > 0 and items then + local ingredients = Craft.getResourceList4(recipe, items, count) + for _,ingredient in pairs(ingredients) do + if ingredient.need > 0 then + local item = self:addCraftingRequest(ingredient, craftList, ingredient.need) + if Craft.findRecipe(item) then + item.status = string.format('%s missing', itemDB:getName(ingredient)) + item.statusCode = self.STATUS_WARNING + else + item.status = 'no recipe' + item.statusCode = self.STATUS_ERROR + end + end + end + end + return crafted +end + +-- Craft as much as possible regardless if all ingredients are available +function Lora:forceCraftItem(inRecipe, items, originalItem, craftList, inCount) + local summed = { } + local throttle = Util.throttle() + + local function sumItems(recipe, count) + count = math.ceil(count / recipe.count) + local craftable = count + + for key,iqty in pairs(Craft.sumIngredients(recipe)) do + throttle() + local item = itemDB:splitKey(key) + local summedItem = summed[key] + if not summedItem then + summedItem = Util.shallowCopy(item) + summedItem.recipe = Craft.findRecipe(item) + summedItem.count = Craft.getItemCount(items, key) + summedItem.need = 0 + summedItem.used = 0 + summedItem.craftable = 0 + summed[key] = summedItem + end + + local total = count * iqty -- 4 * 2 + local used = math.min(summedItem.count, total) -- 5 + local need = total - used -- 3 + + if recipe.craftingTools and recipe.craftingTools[key] then + if summedItem.count > 0 then + summedItem.used = 1 + summedItem.need = 0 + need = 0 + elseif not summedItem.recipe then + summedItem.need = 1 + need = 1 + else + need = 1 + end + else + summedItem.count = summedItem.count - used + summedItem.used = summedItem.used + used + end + + if need > 0 then + if not summedItem.recipe then + craftable = math.min(craftable, math.floor(used / iqty)) + summedItem.need = summedItem.need + need + else + local c = sumItems(summedItem.recipe, need) -- 4 + craftable = math.min(craftable, math.floor((used + c) / iqty)) + summedItem.craftable = summedItem.craftable + c + end + end + end + if craftable > 0 then + craftable = Craft.craftRecipe(recipe, craftable * recipe.count, + self.context.inventoryAdapter) / recipe.count + self:clearGrid() + end + + return craftable * recipe.count + end + + local count = sumItems(inRecipe, inCount) + + if count < inCount then + for _,ingredient in pairs(summed) do + if ingredient.need > 0 then + local item = self:addCraftingRequest(ingredient, craftList, ingredient.need) + if Craft.findRecipe(item) then + item.status = string.format('%s missing', itemDB:getName(ingredient)) + item.statusCode = self.STATUS_WARNING + else + item.status = '(no recipe)' + item.statusCode = self.STATUS_ERROR + end + end + end + end + return count +end + +function Lora:craft(recipe, items, item, craftList) + item.status = nil + item.statusCode = nil + item.crafted = 0 + + if self:isCraftingPaused() then + return + end + + if not self:clearGrid() then + item.status = 'Grid obstructed' + item.statusCode = self.STATUS_ERROR + return + end + + if item.forceCrafting then + item.crafted = self:forceCraftItem(recipe, items, item, craftList, item.count) + else + item.crafted = self:craftItem(recipe, items, item, craftList, item.count) + end +end + +function Lora:craftItems(craftList) + for _,key in pairs(Util.keys(craftList)) do + local item = craftList[key] + if item.count > 0 then + local recipe = Craft.recipes[key] + if recipe then + self:craft(recipe, self:listItems(), item, craftList) + elseif not self.context.controllerAdapter then + item.status = '(no recipe)' + item.statusCode = self.STATUS_ERROR + end + end + end + self:updateCraftingStatus(craftList) + for _,v in pairs(craftList) do + debug(v) + end +end + +return Lora diff --git a/inventoryManager/apis/lora/lora.lua b/inventoryManager/apis/lora/lora.lua deleted file mode 100644 index a274aca..0000000 --- a/inventoryManager/apis/lora/lora.lua +++ /dev/null @@ -1,334 +0,0 @@ -local Craft = require('turtle.craft') -local itemDB = require('itemDB') -local Util = require('util') - -local os = _G.os -local term = _G.term -local turtle = _G.turtle - -local Lora = { - RECIPES_FILE = 'usr/config/recipes.db', - RESOURCE_FILE = 'usr/config/resources.db', - - STATUS_INFO = 'info', - STATUS_WARNING = 'warning', - STATUS_ERROR = 'error', - - tasks = { }, - craftingStatus = { }, -} - -function Lora:init(context) - self.context = context -end - -function Lora:getContext() - return self.context -end - -function Lora:pauseCrafting() - self.craftingPaused = true -end - -function Lora:resumeCrafting() - self.craftingPaused = false -end - -function Lora:isCraftingPaused() - return self.craftingPaused -end - -function Lora:uniqueKey(item) - return table.concat({ item.name, item.damage, item.nbtHash }, ':') -end - -function Lora:getCraftingStatus() - return self.craftingStatus -end - -function Lora:resetCraftingStatus() - self.craftingStatus = { } -end - -function Lora:updateCraftingStatus(list) - for k,v in pairs(list) do - self.craftingStatus[k] = v - end - - self.context.jobList:updateList(self.craftingStatus) -end - -function Lora:registerTask(task) - table.insert(self.tasks, task) -end - -function Lora:showError(msg) - term.clear() - self.context.jobList:showError() - print(msg) - print('rebooting in 5 secs') - os.sleep(5) - os.reboot() -end - -function Lora:getItem(items, inItem, ignoreDamage, ignoreNbtHash) - for _,item in pairs(items) do - if item.name == inItem.name and - (ignoreDamage or item.damage == inItem.damage) and - (ignoreNbtHash or item.nbtHash == inItem.nbtHash) then - return item - end - end -end - -function Lora:getItemWithQty(res, ignoreDamage, ignoreNbtHash) - local items = self:listItems() - local item = self:getItem(items, res, ignoreDamage, ignoreNbtHash) - - if item and (ignoreDamage or ignoreNbtHash) then - local count = 0 - - for _,v in pairs(items) do - if item.name == v.name and - (ignoreDamage or item.damage == v.damage) and - (ignoreNbtHash or item.nbtHash == v.nbtHash) then - count = count + v.count - end - end - item.count = count - end - - return item -end - -function Lora:clearGrid() - local function clear() - turtle.eachFilledSlot(function(slot) - self.context.inventoryAdapter:insert(slot.index, slot.count, nil, slot) - end) - - for i = 1, 16 do - if turtle.getItemCount(i) ~= 0 then - return false - end - end - return true - end - return clear() or clear() -end - -function Lora:eject(item, qty) - local s, m = pcall(function() - self.context.inventoryAdapter:provide(item, qty) - turtle.emptyInventory() - end) - if not s and m then - debug(m) - end -end - -function Lora:saveResources() - local t = { } - - for k,v in pairs(self.context.resources) do - v = Util.shallowCopy(v) - local keys = Util.transpose({ 'auto', 'low', 'limit', - 'ignoreDamage', 'ignoreNbtHash', - 'rsControl', 'rsDevice', 'rsSide' }) - - for _,key in pairs(Util.keys(v)) do - if not keys[key] then - v[key] = nil - end - end - if not Util.empty(v) then - t[k] = v - end - end - - Util.writeTable(Lora.RESOURCE_FILE, t) -end - --- Return a list of everything in the system -function Lora:listItems() - for _ = 1, 5 do - self.items = self.context.inventoryAdapter:listItems() - if self.items then - break - end --- jobList:showError('Error - retrying in 3 seconds') - os.sleep(3) - end - if not self.items then - self:showError('Error - rebooting in 5 seconds') - end - - return self.items -end - -function Lora:addCraftingRequest(item, craftList, count) - local key = self:uniqueKey(item) - local request = craftList[key] - if not craftList[key] then - request = { name = item.name, damage = item.damage, nbtHash = item.nbtHash, count = 0 } - request.displayName = itemDB:getName(request) - craftList[key] = request - end - request.count = request.count + count - return request -end - --- Craft -function Lora:craftItem(recipe, items, originalItem, craftList, count) - local missing = { } - local toCraft = Craft.getCraftableAmount(recipe, count, items, missing) - if missing.name then - originalItem.status = string.format('%s missing', itemDB:getName(missing.name)) - originalItem.statusCode = self.STATUS_WARNING - end - - local crafted = 0 - - if toCraft > 0 then - crafted = Craft.craftRecipe(recipe, toCraft, self.context.inventoryAdapter) - self:clearGrid() - items = self:listItems() - count = count - crafted - end - - if count > 0 and items then - local ingredients = Craft.getResourceList4(recipe, items, count) - for _,ingredient in pairs(ingredients) do - if ingredient.need > 0 then - local item = self:addCraftingRequest(ingredient, craftList, ingredient.need) - if Craft.findRecipe(item) then - item.status = string.format('%s missing', itemDB:getName(ingredient)) - item.statusCode = self.STATUS_WARNING - else - item.status = 'no recipe' - item.statusCode = self.STATUS_ERROR - end - end - end - end - return crafted -end - --- Craft as much as possible regardless if all ingredients are available -function Lora:forceCraftItem(inRecipe, items, originalItem, craftList, inCount) - local summed = { } - local throttle = Util.throttle() - - local function sumItems(recipe, count) - count = math.ceil(count / recipe.count) - local craftable = count - - for key,iqty in pairs(Craft.sumIngredients(recipe)) do - throttle() - local item = itemDB:splitKey(key) - local summedItem = summed[key] - if not summedItem then - summedItem = Util.shallowCopy(item) - summedItem.recipe = Craft.findRecipe(item) - summedItem.count = Craft.getItemCount(items, key) - summedItem.need = 0 - summedItem.used = 0 - summedItem.craftable = 0 - summed[key] = summedItem - end - - local total = count * iqty -- 4 * 2 - local used = math.min(summedItem.count, total) -- 5 - local need = total - used -- 3 - - if recipe.craftingTools and recipe.craftingTools[key] then - if summedItem.count > 0 then - summedItem.used = 1 - summedItem.need = 0 - need = 0 - elseif not summedItem.recipe then - summedItem.need = 1 - need = 1 - else - need = 1 - end - else - summedItem.count = summedItem.count - used - summedItem.used = summedItem.used + used - end - - if need > 0 then - if not summedItem.recipe then - craftable = math.min(craftable, math.floor(used / iqty)) - summedItem.need = summedItem.need + need - else - local c = sumItems(summedItem.recipe, need) -- 4 - craftable = math.min(craftable, math.floor((used + c) / iqty)) - summedItem.craftable = summedItem.craftable + c - end - end - end - if craftable > 0 then - craftable = Craft.craftRecipe(recipe, craftable * recipe.count, - self.context.inventoryAdapter) / recipe.count - self:clearGrid() - end - - return craftable * recipe.count - end - - local count = sumItems(inRecipe, inCount) - - if count < inCount then - for _,ingredient in pairs(summed) do - if ingredient.need > 0 then - local item = self:addCraftingRequest(ingredient, craftList, ingredient.need) - if Craft.findRecipe(item) then - item.status = string.format('%s missing', itemDB:getName(ingredient)) - item.statusCode = self.STATUS_WARNING - else - item.status = '(no recipe)' - item.statusCode = self.STATUS_ERROR - end - end - end - end - return count -end - -function Lora:craft(recipe, items, item, craftList) - item.status = nil - item.statusCode = nil - item.crafted = 0 - - if self:isCraftingPaused() then - return - end - - if not self:clearGrid() then - item.status = 'Grid obstructed' - item.statusCode = self.STATUS_ERROR - return - end - - if item.forceCrafting then - item.crafted = self:forceCraftItem(recipe, items, item, craftList, item.count) - else - item.crafted = self:craftItem(recipe, items, item, craftList, item.count) - end -end - -function Lora:craftItems(craftList) - for _,key in pairs(Util.keys(craftList)) do - local item = craftList[key] - local recipe = Craft.recipes[key] - if recipe then - self:craft(recipe, self:listItems(), item, craftList) - elseif not self.context.controllerAdapter then - item.status = '(no recipe)' - item.statusCode = self.STATUS_ERROR - end - end -end - -return Lora diff --git a/inventoryManager/apis/lora/tasks.lua b/inventoryManager/apis/lora/tasks.lua deleted file mode 100644 index ac3ca07..0000000 --- a/inventoryManager/apis/lora/tasks.lua +++ /dev/null @@ -1,12 +0,0 @@ -local Util = require('util') - -local fs = _G.fs -local shell = _ENV.shell - -local Tasks = { - list = { } -} - - - -return Tasks diff --git a/inventoryManager/apis/networkedAdapter18.lua b/inventoryManager/apis/networkedAdapter18.lua index 936ca08..1313c15 100644 --- a/inventoryManager/apis/networkedAdapter18.lua +++ b/inventoryManager/apis/networkedAdapter18.lua @@ -12,6 +12,7 @@ function NetworkedAdapter:init(args) remoteDefaults = { }, dirty = true, listCount = 0, + activity = { }, } Util.merge(self, defaults) Util.merge(self, args) @@ -43,11 +44,9 @@ listCount = 0, elseif not b.priority then return true end - return a.priority < b.priority + return a.priority > b.priority end) end - -_G._p = self --------------------------------------------- DEBUG end function NetworkedAdapter:isValid() @@ -66,6 +65,10 @@ function NetworkedAdapter:listItems(throttle) end self.listCount = self.listCount + 1 debug(self.listCount) + + -- todo: only listItems from dirty remotes + -- todo: better handling of empty inventories + local cache = { } local items = { } throttle = throttle or Util.throttle() @@ -111,6 +114,7 @@ function NetworkedAdapter:getItemInfo(item) end function NetworkedAdapter:provide(item, qty, slot, direction) + local key = table.concat({ item.name, item.damage, item.nbtHash }, ':') local total = 0 for _, remote in ipairs(self.remotes) do @@ -119,6 +123,8 @@ debug('%s -> slot %d: %d %s', remote.side, slot or -1, qty, item.name) if amount > 0 then self.dirty = true remote.dirty = true + local entry = self.activity[key] or 0 + self.activity[key] = entry + amount end qty = qty - amount total = total + amount @@ -164,9 +170,11 @@ function NetworkedAdapter:insert(slot, qty, toSlot, item, source) local function insert(remote) local amount = remote:insert(slot, qty, toSlot, source or self.direction) if amount > 0 then -debug('%s(%d) -> %s: %d', source or self.direction, slot, remote.side, amount) +debug('%s(%d) -> %s: %d', source or self.localName, slot, remote.side, amount) self.dirty = true remote.dirty = true + local entry = self.activity[key] or 0 + self.activity[key] = entry + amount end qty = qty - amount total = total + amount diff --git a/inventoryManager/apis/turtle/craft.lua b/inventoryManager/apis/turtle/craft.lua index 549fde2..9e1b1a0 100644 --- a/inventoryManager/apis/turtle/craft.lua +++ b/inventoryManager/apis/turtle/craft.lua @@ -1,11 +1,13 @@ local itemDB = require('itemDB') local Util = require('util') +local device = _G.device local fs = _G.fs local turtle = _G.turtle -local RECIPES_DIR = 'usr/etc/recipes' -local USER_RECIPES = 'usr/config/recipes.db' +local RECIPES_DIR = 'usr/etc/recipes' +local USER_RECIPES = 'usr/config/recipes.db' +local MACHINE_LOOKUP = 'usr/config/machine_crafting.db' local Craft = { } @@ -53,6 +55,26 @@ function Craft.getItemCount(items, item) return count end +local function machineCraft(recipe, qty, inventoryAdapter, machineName) + local machine = device[machineName] + if not machine then + debug('machine not found') + else + for k in pairs(recipe.ingredients) do + if machine.getItemMeta(k) then + debug('machine in use: ' .. k) + return false + end + end + + for k,v in pairs(recipe.ingredients) do + inventoryAdapter:provide(splitKey(v), qty, k, machineName) + end + end + + return false +end + local function turtleCraft(recipe, qty, inventoryAdapter) if not clearGrid(inventoryAdapter) then return false @@ -92,6 +114,12 @@ function Craft.loadRecipes() local recipes = Util.readTable(USER_RECIPES) or { } Util.merge(Craft.recipes, recipes) + + for k,v in pairs(Craft.recipes) do + v.result = k + end + + Craft.machineLookup = Util.readTable(MACHINE_LOOKUP) or { } end function Craft.sumIngredients(recipe) @@ -104,6 +132,13 @@ function Craft.sumIngredients(recipe) return t end +local function makeRecipeKey(item) + if type(item) == 'string' then + item = splitKey(item) + end + return table.concat({ item.name, item.damage or 0, item.nbtHash }, ':') +end + function Craft.craftRecipe(recipe, count, inventoryAdapter) if type(recipe) == 'string' then recipe = Craft.recipes[recipe] @@ -142,7 +177,11 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter) local crafted = 0 repeat - if not turtleCraft(recipe, math.min(count, maxCount), inventoryAdapter) then +-- fix + if Craft.machineLookup[recipe.result] then + machineCraft(recipe, math.min(count, maxCount), inventoryAdapter, Craft.machineLookup[recipe.result]) + break + elseif not turtleCraft(recipe, math.min(count, maxCount), inventoryAdapter) then turtle.select(1) break end @@ -154,13 +193,6 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter) return crafted * recipe.count end -local function makeRecipeKey(item) - if type(item) == 'string' then - item = splitKey(item) - end - return table.concat({ item.name, item.damage or 0, item.nbtHash }, ':') -end - function Craft.findRecipe(key) if type(key) ~= 'string' then key = itemDB:makeKey(key) diff --git a/inventoryManager/core/machines.lua b/inventoryManager/core/machines.lua new file mode 100644 index 0000000..675554b --- /dev/null +++ b/inventoryManager/core/machines.lua @@ -0,0 +1,197 @@ +local Config = require('config') +local Lora = require('lora') +local UI = require('ui') +local Util = require('util') + +local colors = _G.colors + +local context = Lora:getContext() + +local machinesPage = UI.Page { + titleBar = UI.TitleBar { + previousPage = true, + title = 'Machines', + }, + grid = UI.ScrollingGrid { + y = 2, ey = -2, + values = context.config.remoteDefaults, + columns = { + { heading = 'Name', key = 'displayName' }, + { heading = 'Priority', key = 'priority', width = 5 }, + { heading = 'Type', key = 'mtype', width = 5 }, + }, + sortColumn = 'displayName', + }, + statusBar = UI.StatusBar { + values = 'Select Machine', + }, +} + +function machinesPage:enable() + self.grid:update() + UI.Page.enable(self) +end + +function machinesPage.grid:getDisplayValues(row) + row = Util.shallowCopy(row) + row.displayName = row.displayName or row.name + return row +end + +function machinesPage.grid:getRowTextColor(row, selected) + if row.mtype == 'ignore' then + return colors.lightGray + end + return UI.Grid:getRowTextColor(row, selected) +end + +function machinesPage:eventHandler(event) + if event.type == 'grid_select' then + UI:setPage('machineWizard', event.selected) + else + UI.Page.eventHandler(self, event) + end + return true +end + +local machineWizard = UI.Page { + titleBar = UI.TitleBar { title = 'Configure' }, + wizard = UI.Wizard { + y = 2, ey = -3, + pages = { + general = UI.Window { + index = 1, + backgroundColor = colors.cyan, + form = UI.Form { + x = 1, y = 2, ex = -1, ey = -2, + manualControls = true, + [1] = UI.TextEntry { + formLabel = 'Name', formKey = 'displayName', + help = 'Set a friendly name', + limit = 64, pruneEmpty = true, + }, + [2] = UI.Chooser { + width = 15, + formLabel = 'Type', formKey = 'mtype', + nochoice = 'Storage', + choices = { + { name = 'Storage', value = 'storage' }, + { name = 'Trashcan', value = 'trashcan' }, + { name = 'Input chest', value = 'input' }, + { name = 'Ignore', value = 'ignore' }, + { name = 'Machine', value = 'machine' }, + }, + help = 'Select type', + }, + }, + }, + confirmation = UI.Window { + title = 'Confirm changes', + index = 2, + grid = UI.TextArea { + x = 2, ex = -2, y = 2, ey = -2, + value = +[[Press accept to save the changes. + +The settings will take effect immediately!]], + }, + }, + }, + }, + statusBar = UI.StatusBar(), + notification = UI.Notification { }, +} + +function machineWizard.wizard.pages.general:enable() + UI.Window.enable(self) + self:focusFirst() +end + +function machineWizard.wizard.pages.general:validate() + return self.form:save() +end + +function machineWizard.wizard:eventHandler(event) + if event.type == 'nextView' and + Util.find(self.pages, 'enabled', true) == self.pages.general then + + if self.pages.general.form:save() then + local index = 2 + for _, page in pairs(self.pages) do + if page.mtype == machineWizard.machine.mtype then + page.index = index + index = index + 1 + elseif page.index ~= 1 then + page.index = nil + end + end + self.pages.confirmation.index = index + return UI.Wizard.eventHandler(self, event) + end + else + return UI.Wizard.eventHandler(self, event) + end +end + +function machineWizard:enable(machine) + self.machine = Util.deepCopy(machine) + self.wizard.pages.general.form:setValues(self.machine) + self.wizard.pages.general.form[1].shadowText = machine.name + + -- restore indices + for _, page in pairs(self.wizard.pages) do + if not page.oindex then + page.oindex = page.index + end + page.index = page.oindex + end + + UI.Page.enable(self) + + for _, v in pairs(self.wizard.pages) do + if v.setMachine then + v:setMachine(self.machine) + end + end +end + +function machineWizard:eventHandler(event) + if event.type == 'cancel' then + UI:setPreviousPage() + + elseif event.type == 'accept' then + + -- todo: no need for calling this function - use validate instead + for _, v in pairs(self.wizard.pages) do + if v.save and v.index then -- only save if the page was valid for this mtype + v:save(self.machine) + end + end + context.config.remoteDefaults[self.machine.name] = self.machine + Config.update('inventoryManagerX', context.config) + + UI:setPreviousPage() + + elseif event.type == 'collapse' then + self.items:hide() + + elseif event.type == 'enable_view' then + local current = event.next or event.prev + self.titleBar.title = current.title or 'Machine' + self.titleBar:draw() + + elseif event.type == 'focus_change' then + self.statusBar:setStatus(event.focused.help) + + elseif event.type == 'form_invalid' then + self.notification:error(event.message) + self:setFocus(event.field) + + else + return UI.Page.eventHandler(self, event) + end + return true +end + +UI:addPage('machines', machinesPage) +UI:addPage('machineWizard', machineWizard) diff --git a/inventoryManager/inventoryManager.lua b/inventoryManager/inventoryManager.lua index 8abadd0..02d08bd 100644 --- a/inventoryManager/inventoryManager.lua +++ b/inventoryManager/inventoryManager.lua @@ -46,6 +46,12 @@ type/monitor - will use the first monitor found side/north - specify a direction (top/bottom/east/etc) name/monitor_1 - specify the exact name of the peripheral + + + + -- Internal + Imports are at < 20 + ]]-- --[[ @@ -60,7 +66,7 @@ _G.requireInjector() local Config = require('config') local Event = require('event') local itemDB = require('itemDB') -local Lora = require('lora/lora') +local Lora = require('lora') local Peripheral = require('peripheral') local UI = require('ui') local Util = require('util') @@ -136,16 +142,19 @@ local context = { Lora:init(context) -local programDir = fs.getDir(shell.getRunningProgram()) -local pluginDir = fs.combine(programDir, 'plugins') - -for _, file in pairs(fs.list(pluginDir)) do - local s, m = Util.run(_ENV, fs.combine(pluginDir, file)) - if not s and m then - error(m or 'Unknown error') +local function loadDirectory(dir) + for _, file in pairs(fs.list(dir)) do + local s, m = Util.run(_ENV, fs.combine(dir, file)) + if not s and m then + error(m or 'Unknown error') + end end end +local programDir = fs.getDir(shell.getRunningProgram()) +loadDirectory(fs.combine(programDir, 'core')) +loadDirectory(fs.combine(programDir, 'plugins')) + table.sort(Lora.tasks, function(a, b) return a.priority < b.priority end) @@ -162,7 +171,11 @@ Event.onInterval(5, function() context.inventoryAdapter:refresh() for _, task in ipairs(Lora.tasks) do - task:cycle(context) + local s, m = pcall(function() task:cycle(context) end) + if not s and m then + Util.print(task) + error(m) + end end end end) diff --git a/inventoryManager/plugins/autocraftTask.lua b/inventoryManager/plugins/autocraftTask.lua index 2d089d9..697e5ff 100644 --- a/inventoryManager/plugins/autocraftTask.lua +++ b/inventoryManager/plugins/autocraftTask.lua @@ -1,4 +1,4 @@ -local Lora = require('lora/lora') +local Lora = require('lora') local Util = require('util') local Autocraft = { @@ -17,8 +17,8 @@ function Autocraft:cycle(context) end if not Util.empty(list) then - Lora:craftItems(list) - end + Lora:craftItems(list) + end end Lora:registerTask(Autocraft) diff --git a/inventoryManager/plugins/craft.lua b/inventoryManager/plugins/demandCraft.lua similarity index 76% rename from inventoryManager/plugins/craft.lua rename to inventoryManager/plugins/demandCraft.lua index e7b4f39..6a0c635 100644 --- a/inventoryManager/plugins/craft.lua +++ b/inventoryManager/plugins/demandCraft.lua @@ -1,10 +1,10 @@ -local Craft = require('turtle.craft') -local itemDB = require('itemDB') -local Lora = require('lora/lora') -local UI = require('ui') -local Util = require('util') +local Craft = require('turtle.craft') +local itemDB = require('itemDB') +local Lora = require('lora') +local UI = require('ui') +local Util = require('util') -local colors = _G.colors +local colors = _G.colors local demandCrafting = { } @@ -135,25 +135,35 @@ local demandCraftingTask = { priority = 20, } -function demandCraftingTask:cycle() - if Util.size(demandCrafting) > 0 then - local demandCrafted = Util.shallowCopy(demandCrafting) - Lora:craftItems(demandCrafted) +function demandCraftingTask:cycle(context) + local demandCrafted = { } - for _, item in pairs(demandCrafting) do - if item.crafted then - item.count = math.max(0, item.count - item.crafted) - if item.count <= 0 then - item.statusCode = 'success' - end - end + -- look directly at the adapter import activity to determine + -- if the item was imported into storage from any source. + -- The item does NOT need to come from the machine that did + -- the crafting. + for _,key in pairs(Util.keys(demandCrafting)) do + local item = demandCrafting[key] + + local imported = context.inventoryAdapter.activity[key] + if imported then + item.crafted = math.min(imported, item.count) + item.count = math.max(0, item.count - item.crafted) + context.inventoryAdapter.activity[key] = imported - item.crafted end + demandCrafted[key] = item + end - Lora:updateCraftingStatus(demandCrafted) + if Util.size(demandCrafted) > 0 then + Lora:craftItems(demandCrafted) + end - for _,key in pairs(Util.keys(demandCrafting)) do - local item = demandCrafting[key] - if item.crafted and item.count <= 0 then + for _,key in pairs(Util.keys(demandCrafting)) do + local item = demandCrafting[key] + if item.crafted then + item.count = math.max(0, item.count - item.crafted) + if item.count <= 0 then + item.statusCode = 'success' demandCrafting[key] = nil if item.eject then Lora:eject(item, item.ocount) diff --git a/inventoryManager/plugins/exportTask.lua b/inventoryManager/plugins/exportTask.lua index 6e26330..937610a 100644 --- a/inventoryManager/plugins/exportTask.lua +++ b/inventoryManager/plugins/exportTask.lua @@ -1,5 +1,5 @@ local itemDB = require('itemDB') -local Lora = require('lora/lora') +local Lora = require('lora') local device = _G.device @@ -12,19 +12,20 @@ function ExportTask:cycle(context) if v.exports then local machine = device[target] if machine and machine.getItemMeta then - for slotNo, item in pairs(v.exports) do - local slot = machine.getItemMeta(slotNo) or { count = 0 } - local maxCount = slot.maxCount or itemDB:getMaxCount(item) + for _, entry in pairs(v.exports) do + local slot = machine.getItemMeta(entry.slot) or { count = 0 } + local maxCount = slot.maxCount or itemDB:getMaxCount(entry.name) local count = maxCount - slot.count if count > 0 then - context.inventoryAdapter:provide(itemDB:splitKey(item), count, slotNo, target) + context.inventoryAdapter:provide( + itemDB:splitKey(entry.name), count, entry.slot, target) end end else debug('Invalid export target: ' .. target) end end - end + end end Lora:registerTask(ExportTask) diff --git a/inventoryManager/plugins/exportView.lua b/inventoryManager/plugins/exportView.lua new file mode 100644 index 0000000..fbdc130 --- /dev/null +++ b/inventoryManager/plugins/exportView.lua @@ -0,0 +1,121 @@ +local itemDB = require('itemDB') +local Lora = require('lora') +local UI = require('ui') +local Util = require('util') + +local colors = _G.colors +local device = _G.device + +local itemSlideout = UI.SlideOut { + backgroundColor = colors.cyan, + grid = UI.ScrollingGrid { + y = 3, ey = -2, + columns = { + { heading = 'Name', key = 'displayName', width = 31 }, + { heading = 'Qty', key = 'count' , width = 5 }, + }, + sortColumn = 'displayName', + }, + filter = UI.TextEntry { + x = 2, ex = -2, y = 2, + limit = 50, + shadowText = 'filter', + backgroundColor = colors.lightGray, + backgroundFocusColor = colors.lightGray, + }, + button1 = UI.Button { + x = -14, y = -1, + text = 'Ok', event = 'accept', + }, + button2 = UI.Button { + x = -9, y = -1, + text = 'Cancel', event = 'collapse', + }, +} + +function itemSlideout:filterItems(t, filter) + if filter then + local r = {} + filter = filter:lower() + for _,v in pairs(t) do + if string.find(v.lname, filter) then + table.insert(r, v) + end + end + return r + end + return t +end + +function itemSlideout.grid:enable() + if not self.allItems then + self.allItems = Lora:listItems() + Lora:mergeResources(self.allItems) + self:setValues(self.allItems) + end + UI.Grid.enable(self) +end + +function itemSlideout:eventHandler(event) + if event.type == 'text_change' and event.element == self.filter then + local t = self:filterItems(self.grid.allItems, event.text) + self.grid:setValues(t) + self.grid:draw() + end + return UI.SlideOut.eventHandler(self, event) +end + +local exportView = UI.Window { + mtype = 'machine', + title = 'Export item into machine', + index = 3, + grid = UI.ScrollingGrid { + x = 2, ex = -6, y = 2, ey = -2, + columns = { + { heading = 'Slot', key = 'slot', width = 4 }, + { heading = 'Item', key = 'displayName' }, + }, + sortColumn = 'slot', + }, + add = UI.Button { + x = -4, y = 4, + text = '+', event = 'add_export', help = '...', + }, + remove = UI.Button { + x = -4, y = 6, + text = '-', event = 'remove_export', help = '...', + }, +} + +function exportView:save(machine) + machine.exports = not Util.empty(self.grid.values) and self.grid.values or nil + return true +end + +function exportView:setMachine(machine) + local m = device[machine.name] + self.slotCount = m.size() + self.grid:setValues(machine.exports or { }) +end + +function exportView.grid:getDisplayValues(row) + row = Util.shallowCopy(row) + row.displayName = itemDB:getName(row.name) + return row +end + +function exportView:eventHandler(event) + if event.type == 'grid_select' or event.type == 'add_export' then + itemSlideout:show() + elseif event.type == 'remove_export' then + local row = self.grid:getSelected() + if row then + Util.removeByValue(self.grid.values, row) + self.grid:update() + self.grid:draw() + end + end +end + +UI:getPage('machineWizard'):add({ items = itemSlideout }) +UI:getPage('machineWizard').wizard:add({ export = exportView }) diff --git a/inventoryManager/plugins/importTask.lua b/inventoryManager/plugins/importTask.lua index 165790b..b9fc3a3 100644 --- a/inventoryManager/plugins/importTask.lua +++ b/inventoryManager/plugins/importTask.lua @@ -1,4 +1,4 @@ -local Lora = require('lora/lora') +local Lora = require('lora') local device = _G.device @@ -21,7 +21,7 @@ function ImportTask:cycle(context) debug('Invalid import source: ' .. source) end end - end + end end Lora:registerTask(ImportTask) diff --git a/inventoryManager/plugins/importView.lua b/inventoryManager/plugins/importView.lua new file mode 100644 index 0000000..92abe68 --- /dev/null +++ b/inventoryManager/plugins/importView.lua @@ -0,0 +1,56 @@ +local UI = require('ui') +local Util = require('util') + +local device = _G.device + +local importView = UI.Window { + mtype = 'machine', + title = 'Import item from machine', + index = 4, + grid = UI.ScrollingGrid { + y = 2, ey = -2, + columns = { + { heading = 'Slot', key = 'slot', width = 4 }, + { heading = 'Import', key = 'import' }, + }, + sortColumn = 'slot', + help = 'Double-click to toggle' + }, +} + +function importView:setMachine(machine) + local m = device[machine.name] + + local t = { } + for k = 1, m.size() do + t[k] = { slot = k } + end + + if machine.imports then + for k,v in pairs(machine.imports) do + t[k] = { slot = k, import = v } + end + end + + self.grid:setValues(t) +end + +function importView:save(machine) + local t = { } + for k,v in pairs(self.grid.values) do + if v.import then + t[k] = true + end + end + machine.imports = not Util.empty(t) and t or nil + return true +end + +function importView:eventHandler(event) + if event.type == 'grid_select' then + event.selected.import = not event.selected.import + self.grid:draw() + end +end + +UI:getPage('machineWizard').wizard:add({ import = importView }) diff --git a/inventoryManager/plugins/inputChestTask.lua b/inventoryManager/plugins/inputChestTask.lua index 6589275..29e5dcc 100644 --- a/inventoryManager/plugins/inputChestTask.lua +++ b/inventoryManager/plugins/inputChestTask.lua @@ -1,38 +1,24 @@ -local InventoryAdapter = require('inventoryAdapter') -local Lora = require('lora/lora') +local Lora = require('lora') local device = _G.device -local modem = device.wired_modem local InputChest = { priority = 1, - adapters = { }, } -function InputChest:init(context) - for k,v in pairs(context.config.remoteDefaults) do - if v.mtype == 'input' then - local adapter = InventoryAdapter.wrap({ side = k, direction = modem.getNameLocal() }) - if adapter then - table.insert(self.adapters, adapter) - end - end +function InputChest:cycle(context) + for name,v in pairs(context.config.remoteDefaults) do + if v.mtype == 'input' then + local inventory = device[name] + + local list = inventory and inventory.list and inventory.list() + if list then + for slotNo, slot in pairs(list) do + context.inventoryAdapter:insert(slotNo, slot.count, nil, slot, name) + end + end + end end end --- TODO: clear grid --- TODO: extract directly to target - -function InputChest:cycle(context) - for _, adapter in pairs(self.adapters) do - local list = adapter.list() -- raw list ! - for k,v in pairs(list) do - adapter:extract(k, v.count, 1) - context.inventoryAdapter:insert(1, v.count, nil, v) - end - end -end - -InputChest:init(Lora:getContext()) - Lora:registerTask(InputChest) diff --git a/inventoryManager/plugins/item.lua b/inventoryManager/plugins/item.lua index e6c8b0c..bcbe553 100644 --- a/inventoryManager/plugins/item.lua +++ b/inventoryManager/plugins/item.lua @@ -1,5 +1,5 @@ local Ansi = require('ansi') -local Lora = require('lora/lora') +local Lora = require('lora') local UI = require('ui') local Util = require('util') @@ -24,6 +24,7 @@ local itemPage = UI.Page { width = 7, formLabel = 'Max', formKey = 'limit', help = 'Eject if above max' }, +--[[ [3] = UI.Chooser { width = 7, formLabel = 'Autocraft', formKey = 'auto', @@ -34,6 +35,7 @@ local itemPage = UI.Page { }, help = 'Craft until out of ingredients' }, +]] [4] = UI.Chooser { width = 7, formLabel = 'Ignore Dmg', formKey = 'ignoreDamage', @@ -125,9 +127,9 @@ local itemPage = UI.Page { } function itemPage:enable(item) - self.item = item + self.item = Util.shallowCopy(item) - self.form:setValues(item) + self.form:setValues(self.item) self.titleBar.title = item.displayName or item.name UI.Page.enable(self) diff --git a/inventoryManager/plugins/jobList.lua b/inventoryManager/plugins/jobList.lua index 3b4e7c5..efba70f 100644 --- a/inventoryManager/plugins/jobList.lua +++ b/inventoryManager/plugins/jobList.lua @@ -1,4 +1,4 @@ -local Lora = require('lora/lora') +local Lora = require('lora') local Peripheral = require('peripheral') local UI = require('ui') diff --git a/inventoryManager/plugins/learn.lua b/inventoryManager/plugins/learn.lua index 139b55f..a8ebf06 100644 --- a/inventoryManager/plugins/learn.lua +++ b/inventoryManager/plugins/learn.lua @@ -1,6 +1,6 @@ local Craft = require('turtle.craft') local itemDB = require('itemDB') -local Lora = require('lora/lora') +local Lora = require('lora') local UI = require('ui') local Util = require('util') diff --git a/inventoryManager/plugins/limitTask.lua b/inventoryManager/plugins/limitTask.lua index 3fc86d7..82767d3 100644 --- a/inventoryManager/plugins/limitTask.lua +++ b/inventoryManager/plugins/limitTask.lua @@ -1,36 +1,35 @@ -local Lora = require('lora/lora') +local Lora = require('lora') local LimitTask = { priority = 10, } -function LimitTask:init(context) - for k,v in pairs(context.config.remoteDefaults) do - if v.mtype == 'trashcan' then - self.trashcan = k - break - end - end -end - function LimitTask:cycle(context) - if not self.trashcan then + local trashcan + + for k,v in pairs(context.config.remoteDefaults) do + if v.mtype == 'trashcan' then + trashcan = k + break + end + end + + if not trashcan then return end - for _,res in pairs(context.resources) do + for _,res in pairs(context.resources) do if res.limit then - local item = Lora:getItemWithQty(res, res.ignoreDamage, res.ignoreNbtHash) - if item and item.count > res.limit then - context.inventoryAdapter:provide( - { name = item.name, damage = item.damage, nbtHash = item.nbtHash }, - item.count - res.limit, - nil, - self.trashcan) - end - end - end + local item = Lora:getItemWithQty(res, res.ignoreDamage, res.ignoreNbtHash) + if item and item.count > res.limit then + context.inventoryAdapter:provide( + { name = item.name, damage = item.damage, nbtHash = item.nbtHash }, + item.count - res.limit, + nil, + trashcan) + end + end + end end -LimitTask:init(Lora:getContext()) Lora:registerTask(LimitTask) diff --git a/inventoryManager/plugins/listing.lua b/inventoryManager/plugins/listing.lua index 652e885..8a9aeb8 100644 --- a/inventoryManager/plugins/listing.lua +++ b/inventoryManager/plugins/listing.lua @@ -1,13 +1,13 @@ local Craft = require('turtle.craft') local itemDB = require('itemDB') -local Lora = require('lora/lora') +local Lora = require('lora') local UI = require('ui') local Util = require('util') local colors = _G.colors local os = _G.os -local context = Lora:getContext() +local context = Lora:getContext() local function queue(fn) while Lora:isCraftingPaused() do @@ -16,37 +16,6 @@ local function queue(fn) fn() end -local function mergeResources(t) - for _,v in pairs(context.resources) do - local item = Lora:getItem(t, v) - if item then - Util.merge(item, v) - else - item = Util.shallowCopy(v) - item.count = 0 - table.insert(t, item) - end - end - - for k in pairs(Craft.recipes) do - local v = itemDB:splitKey(k) - local item = Lora:getItem(t, v) - if not item then - item = Util.shallowCopy(v) - item.count = 0 - table.insert(t, item) - end - item.has_recipe = true - end - - for _,v in pairs(t) do - if not v.displayName then - v.displayName = itemDB:getName(v) - end - v.lname = v.displayName:lower() - end -end - local function filterItems(t, filter, displayMode) if filter or displayMode > 0 then local r = { } @@ -80,8 +49,8 @@ local listingPage = UI.Page { grid = UI.Grid { y = 2, ey = -2, columns = { + { heading = ' Qty', key = 'count' , width = 4, justify = 'right' }, { heading = 'Name', key = 'displayName' }, - { heading = 'Qty', key = 'count' , width = 4 }, { heading = 'Min', key = 'low' , width = 4 }, { heading = 'Max', key = 'limit' , width = 4 }, }, @@ -95,6 +64,9 @@ local listingPage = UI.Page { shadowTextColor = colors.gray, backgroundColor = colors.cyan, backgroundFocusColor = colors.cyan, + accelerators = { + [ 'enter' ] = 'craft', + }, }, display = UI.Button { x = -3, @@ -107,7 +79,6 @@ local listingPage = UI.Page { accelerators = { r = 'refresh', q = 'quit', - grid_select_right = 'craft', [ 'control-e' ] = 'eject', [ 'control-s' ] = 'eject_stack', [ 'control-m' ] = 'machines', @@ -131,7 +102,7 @@ end function listingPage.grid:getDisplayValues(row) row = Util.shallowCopy(row) - row.count = Util.toBytes(row.count) + row.count = row.count > 0 and Util.toBytes(row.count) or '' if row.low then row.low = Util.toBytes(row.low) end @@ -142,6 +113,7 @@ function listingPage.grid:getDisplayValues(row) end function listingPage:eventHandler(event) +debug(event) if event.type == 'quit' then UI:exitPullEvents() @@ -160,9 +132,11 @@ function listingPage:eventHandler(event) elseif event.type == 'machines' then UI:setPage('machines') - elseif event.type == 'grid_select' then - local selected = event.selected - UI:setPage('item', selected) + elseif event.type == 'details' or event.type == 'grid_select_right' then + local item = self.grid:getSelected() + if item then + UI:setPage('item', item) + end elseif event.type == 'refresh' then self:refresh() @@ -186,7 +160,7 @@ function listingPage:eventHandler(event) elseif event.type == 'learn' then UI:setPage('learn') - elseif event.type == 'craft' or event.type == 'grid_select_right' then + elseif event.type == 'craft' or event.type == 'grid_select' then local item = self.grid:getSelected() if Craft.findRecipe(item) or true then -- or item.is_craftable then UI:setPage('craft', self.grid:getSelected()) @@ -238,7 +212,7 @@ end function listingPage:refresh() self.allItems = Lora:listItems() - mergeResources(self.allItems) + Lora:mergeResources(self.allItems) self:applyFilter() end diff --git a/inventoryManager/plugins/machines.lua b/inventoryManager/plugins/machines.lua deleted file mode 100644 index 4ded5d8..0000000 --- a/inventoryManager/plugins/machines.lua +++ /dev/null @@ -1,152 +0,0 @@ -local Config = require('config') -local Lora = require('lora/lora') -local UI = require('ui') -local Util = require('util') - -local colors = _G.colors - -local context = Lora:getContext() - -local machinesPage = UI.Page { - titleBar = UI.TitleBar { - previousPage = true, - title = 'Machines', - }, - grid = UI.ScrollingGrid { - y = 2, ey = -2, - values = context.config.remoteDefaults, - columns = { - { heading = 'Name', key = 'displayName' }, - { heading = 'Priority', key = 'priority', width = 5 }, - { heading = 'Type', key = 'mtype', width = 5 }, - }, - sortColumn = 'name', - }, - detail = UI.SlideOut { - backgroundColor = colors.cyan, - form = UI.Form { - x = 1, y = 2, ex = -1, ey = -2, - [7] = UI.Text { - x = 12, y = 1, - width = 28, - }, - [1] = UI.TextEntry { - formLabel = 'Name', formKey = 'displayName', help = '...', - limit = 64, - }, - [2] = UI.Chooser { - width = 15, - formLabel = 'Type', formKey = 'mtype', - nochoice = 'Storage', - choices = { - { name = 'Storage', value = 'storage' }, - { name = 'Trashcan', value = 'trashcan' }, - { name = 'Input chest', value = 'input' }, - { name = 'Ignore', value = 'ignore' }, - }, - help = 'Check if machine is empty before crafting' - }, - [3] = UI.Chooser { - width = 7, - formLabel = 'Empty', formKey = 'empty', - nochoice = 'No', - choices = { - { name = 'Yes', value = true }, - { name = 'No', value = false }, - }, - help = 'Check if machine is empty before crafting' - }, - [4] = UI.TextEntry { - formLabel = 'Priority', formKey = 'priority', help = '...', - limit = 4, - }, - [5] = UI.TextEntry { - formLabel = 'Max Craft', formKey = 'maxCount', help = '...', - limit = 4, - }, - [6] = UI.TextEntry { - formLabel = 'Lock to', formKey = 'lockWith', help = '...', - width = 18, - limit = 64, - }, - [8] = UI.Button { - x = -9, ey = -4, - text = 'Detect', help = '...', - limit = 64, - }, - }, - statusBar = UI.StatusBar(), - }, - statusBar = UI.StatusBar { - values = 'Select Machine', - }, - accelerators = { - h = 'toggle_hidden', - } -} - -function machinesPage:enable() - self.grid:update() - UI.Page.enable(self) -end - -function machinesPage.detail:eventHandler(event) - if event.type == 'focus_change' then - self.statusBar:setStatus(event.focused.help) - end - return UI.SlideOut.eventHandler(self, event) -end - -function machinesPage.grid:getDisplayValues(row) - row = Util.shallowCopy(row) - row.displayName = row.displayName or row.name - return row -end - -function machinesPage.grid:getRowTextColor(row, selected) - if row.mtype == 'ignore' then - return colors.lightGray - end - return UI.Grid:getRowTextColor(row, selected) -end - -function machinesPage:eventHandler(event) - if event.type == 'grid_select' then - self.detail.form:setValues(event.selected) - self.detail.form[7].value = event.selected.name -debug(event.selected) - self.detail:show() - - elseif event.type == 'toggle_hidden' then - local selected = self.grid:getSelected() - if selected then - selected.ignore = not selected.ignore --- Util.writeTable(MACHINES_FILE, machines) - self:draw() - end - - elseif event.type == 'form_complete' then - self.detail.form.values.empty = self.detail.form.values.empty == true or nil - self.detail.form.values.ignore = self.detail.form.values.ignore == true or nil - self.detail.form.values.priority = tonumber(self.detail.form.values.priority) - self.detail.form.values.maxCount = tonumber(self.detail.form.values.maxCount) - if #self.detail.form.values.displayName == 0 then - self.detail.form.values.displayName = nil - end - if #self.detail.form.values.lockWith == 0 then - self.detail.form.values.lockWith = nil - end - Config.update('inventoryManager', context.config) - self.detail:hide() - self.grid:update() - - elseif event.type == 'form_cancel' then - self.detail:hide() - - else - UI.Page.eventHandler(self, event) - end - return true -end - -UI:addPage('machines', machinesPage) diff --git a/inventoryManager/plugins/replenishTask.lua b/inventoryManager/plugins/replenishTask.lua index f06ac0e..1568f5b 100644 --- a/inventoryManager/plugins/replenishTask.lua +++ b/inventoryManager/plugins/replenishTask.lua @@ -1,5 +1,5 @@ local itemDB = require('itemDB') -local Lora = require('lora/lora') +local Lora = require('lora') local ReplenishTask = { priority = 30, @@ -41,7 +41,6 @@ function ReplenishTask:cycle(context) end Lora:craftItems(craftList) - Lora:updateCraftingStatus(craftList) end Lora:registerTask(ReplenishTask) diff --git a/inventoryManager/plugins/storageView.lua b/inventoryManager/plugins/storageView.lua new file mode 100644 index 0000000..9a855bd --- /dev/null +++ b/inventoryManager/plugins/storageView.lua @@ -0,0 +1,44 @@ +local UI = require('ui') + +local colors = _G.colors + +local storageView = UI.Window { + mtype = 'storage', + title = 'Storage Options', + index = 2, + backgroundColor = colors.cyan, + form = UI.Form { + x = 1, y = 2, ex = -1, ey = -2, + manualControls = true, + [1] = UI.TextEntry { + formLabel = 'Priority', formKey = 'priority', + help = 'Larger values get precedence', + limit = 4, + validate = 'numeric', pruneEmpty = true, + }, + [2] = UI.TextEntry { + formLabel = 'Lock to', formKey = 'lockWith', + help = 'Locks chest to a single item type', + width = 18, limit = 64, pruneEmpty = true, + }, + [3] = UI.Button { + x = -9, ey = -4, + text = 'Detect', help = 'Determine what is currently present', + }, + }, +} + +function storageView:enable() + UI.Window.enable(self) + self:focusFirst() +end + +function storageView:validate() + return self.form:save() +end + +function storageView:setMachine(machine) + self.form:setValues(machine) +end + +UI:getPage('machineWizard').wizard:add({ storage = storageView })