From 1c70085450a410d5c6dfb145ceb7bd0cf4b711c3 Mon Sep 17 00:00:00 2001 From: kepler155c Date: Sun, 28 Oct 2018 15:24:12 -0400 Subject: [PATCH] milo storage filter + crafting fixes --- milo/apis/storage.lua | 49 ++++++++++++------ milo/apis/turtle/craft.lua | 39 +++++++++++---- milo/plugins/exportTask.lua | 59 ++++++++++------------ milo/plugins/importTask.lua | 63 +++++++++++------------ milo/plugins/inputChestTask.lua | 15 ++---- milo/plugins/limitTask.lua | 33 +++++------- milo/plugins/potionImportTask.lua | 83 +++++++++++++++---------------- milo/plugins/redstoneTask.lua | 4 +- 8 files changed, 177 insertions(+), 168 deletions(-) diff --git a/milo/apis/storage.lua b/milo/apis/storage.lua index dc0ab7b..f7c3422 100644 --- a/milo/apis/storage.lua +++ b/milo/apis/storage.lua @@ -7,9 +7,9 @@ local Util = require('util') local device = _G.device local os = _G.os -local NetworkedAdapter = class() +local Storage = class() -function NetworkedAdapter:init(args) +function Storage:init(args) local defaults = { remoteDefaults = { }, dirty = true, @@ -32,7 +32,7 @@ debug('%s: %s', e, tostring(dev)) end) end -function NetworkedAdapter:showStorage() +function Storage:showStorage() local t = { } for k,v in pairs(self.remoteDefaults) do local online = v.adapter and v.adapter.online @@ -49,7 +49,7 @@ function NetworkedAdapter:showStorage() end end -function NetworkedAdapter:setOnline(online) +function Storage:setOnline(online) if online ~= self.storageOnline then self.storageOnline = online os.queueEvent(self.storageOnline and 'storage_online' or 'storage_offline', online) @@ -57,11 +57,11 @@ function NetworkedAdapter:setOnline(online) end end -function NetworkedAdapter:isOnline() +function Storage:isOnline() return self.storageOnline end -function NetworkedAdapter:initStorage() +function Storage:initStorage() local online = true debug('Initializing storage') @@ -80,7 +80,24 @@ function NetworkedAdapter:initStorage() self:setOnline(online) end -function NetworkedAdapter:onlineAdapters(reversed) +function Storage:filterActive(mtype, filter) + local iter = { } + for _, v in pairs(self.remoteDefaults) do + if v.adapter and v.adapter.online and v.mtype == mtype then + if not filter or filter(v) then + table.insert(iter, v) + end + end + end + + local i = 0 + return function() + i = i + 1 + return iter[i] + end +end + +function Storage:onlineAdapters(reversed) local iter = { } for _, v in pairs(self.remoteDefaults) do if v.adapter and v.adapter.online and v.mtype == 'storage' then @@ -113,13 +130,13 @@ function NetworkedAdapter:onlineAdapters(reversed) end end -function NetworkedAdapter:refresh(throttle) +function Storage:refresh(throttle) self.dirty = true return self:listItems(throttle) end -- provide a consolidated list of items -function NetworkedAdapter:listItems(throttle) +function Storage:listItems(throttle) if not self.dirty then return self.items end @@ -160,11 +177,11 @@ self.listCount = self.listCount + 1 return items end -function NetworkedAdapter:export(target, slot, count, item) +function Storage:export(target, slot, count, item) return self:provide(item, count, slot, target) end -function NetworkedAdapter:provide(item, qty, slot, direction) +function Storage:provide(item, qty, slot, direction) local total = 0 for _, adapter in self:onlineAdapters() do @@ -186,7 +203,7 @@ debug('EXT: %s(%d): %s -> %s%s', return total end -function NetworkedAdapter:trash(source, slot, count) +function Storage:trash(source, slot, count) local trashcan = Util.find(self.remoteDefaults, 'mtype', 'trashcan') if trashcan and trashcan.adapter and trashcan.adapter.online then debug('TRA: %s[%d] (%d)', source or self.localName, slot, count or 64) @@ -195,16 +212,16 @@ debug('TRA: %s[%d] (%d)', source or self.localName, slot, count or 64) return 0 end -function NetworkedAdapter:import(source, slot, count, item) +function Storage:import(source, slot, count, item) return self:insert(slot, count, nil, item, source) end -function NetworkedAdapter:insert(slot, qty, toSlot, item, source) +function Storage:insert(slot, qty, toSlot, item, source) local total = 0 -- toSlot is not really valid with this adapter if toSlot then - error('NetworkedAdapter: toSlot is not valid') + error('Storage: toSlot is not valid') end local key = table.concat({ item.name, item.damage, item.nbtHash }, ':') @@ -265,4 +282,4 @@ debug('INS: %s(%d): %s[%d] -> %s', return total end -return NetworkedAdapter +return Storage diff --git a/milo/apis/turtle/craft.lua b/milo/apis/turtle/craft.lua index a36cfd1..6e891a0 100644 --- a/milo/apis/turtle/craft.lua +++ b/milo/apis/turtle/craft.lua @@ -137,8 +137,6 @@ local function turtleCraft(recipe, inventoryAdapter, request, count) turtle.select(1) if turtle.craft() then - request.status = nil - request.statusCode = Craft.STATUS_SUCCESS request.crafted = request.crafted + count * recipe.count return true end @@ -154,13 +152,36 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter, origItem) end end - for _,key in pairs(Util.keys(origItem.ingredients)) do - local e = origItem.ingredients[key] - if e and e.transient then - origItem.ingredients[key] = nil + -- wait til all requests have been completed + local isPending = false + for key, request in pairs(origItem.ingredients) do + if request.pending then + local irecipe = Craft.findRecipe(key) + machineCraft(irecipe, inventoryAdapter, + Craft.machineLookup[irecipe.result], request) + isPending = request.pending or isPending end end - return Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) + + local crafted = 0 + --if not isPending then + for _,key in pairs(Util.keys(origItem.ingredients)) do + local e = origItem.ingredients[key] + if e and e.transient then + origItem.ingredients[key] = nil + end + end + crafted = Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) + --end + + for _, request in pairs(origItem.ingredients) do + if request.crafted >= request.count then + request.status = nil + request.statusCode = Craft.STATUS_SUCCESS + end + end + + return crafted end function Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) @@ -179,8 +200,8 @@ function Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) end if request.pending then - machineCraft(recipe, inventoryAdapter, - Craft.machineLookup[recipe.result], request) + --machineCraft(recipe, inventoryAdapter, + -- Craft.machineLookup[recipe.result], request) return 0 end diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index 8d2eec4..5d864d9 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -1,49 +1,44 @@ local itemDB = require('itemDB') local Milo = require('milo') -local device = _G.device - local ExportTask = { name = 'exporter', priority = 40, } +local function filter(a) + return a.exports +end + function ExportTask:cycle(context) - for target, v in pairs(context.config.remoteDefaults) do - if v.exports then - local machine = device[target] - if machine and machine.getItemMeta then - for _, entry in pairs(v.exports) do - local slotNo = type(entry.slot) == 'number' and entry.slot or nil -- '*' indicates any slot + for machine in context.storage:filterActive('machine', filter) do + for _, entry in pairs(machine.exports) do + local slotNo = type(entry.slot) == 'number' and entry.slot or nil -- '*' indicates any slot - local slot = (slotNo and machine.getItemMeta(slotNo)) or { count = 0 } - for key in pairs(entry.filter) do - local item = itemDB:splitKey(key) + local slot = (slotNo and machine.adapter.getItemMeta(slotNo)) or { count = 0 } + for key in pairs(entry.filter or { }) do + local item = itemDB:splitKey(key) - -- is something else is in this slot - if not slot.name or slot.name == item.name then - local maxCount = slot.maxCount or itemDB:getMaxCount(item) - local count = maxCount - slot.count - if not slotNo then - -- TODO: should we just execute export - - -- or scan all slots for space ?? - count = machine.size() * maxCount - slot.count - end - if count > 0 then - item = Milo:getItemWithQty(item) - if item and count > 0 then - context.storage:export( - target, - slotNo, - math.min(count, item.count), - item) - end - end + -- is something else is in this slot + if not slot.name or slot.name == item.name then + local maxCount = slot.maxCount or itemDB:getMaxCount(item) + local count = maxCount - slot.count + if not slotNo then + -- TODO: should we just execute export - + -- or scan all slots for space ?? + count = machine.adapter.size() * maxCount - slot.count + end + if count > 0 then + item = Milo:getItemWithQty(item) + if item and count > 0 then + context.storage:export( + machine.name, + slotNo, + math.min(count, item.count), + item) end end end - else - debug('Invalid export target: ' .. target) end end end diff --git a/milo/plugins/importTask.lua b/milo/plugins/importTask.lua index 0e26156..0b27c52 100644 --- a/milo/plugins/importTask.lua +++ b/milo/plugins/importTask.lua @@ -1,48 +1,43 @@ local Milo = require('milo') -local device = _G.device - local ImportTask = { name = 'importer', priority = 20, } +local function filter(a) + return a.imports +end + function ImportTask:cycle(context) - for source, v in pairs(context.config.remoteDefaults) do - if v.imports then - local inventory = device[source] - if inventory then - for _, entry in pairs(v.imports) do + for inventory in context.storage:filterActive('machine', filter) do + for _, entry in pairs(inventory.imports) do - local function matchesFilter(item) - if not entry.filter then - return true - end - - local key = Milo:uniqueKey(item) - if entry.blacklist then - return not entry.filter[key] - end - return entry.filter[key] - end - - local function importSlot(slotNo) - local item = inventory.getItemMeta(slotNo) - if item and matchesFilter(item) then - context.storage:import(source, slotNo, item.count, item) - end - end - - if type(entry.slot) == 'number' then - importSlot(entry.slot) - else - for i = 1, inventory.size() do - importSlot(i) - end - end + local function matchesFilter(item) + if not entry.filter then + return true end + + local key = Milo:uniqueKey(item) + if entry.blacklist then + return not entry.filter[key] + end + return entry.filter[key] + end + + local function importSlot(slotNo) + local item = inventory.adapter.getItemMeta(slotNo) + if item and matchesFilter(item) then + context.storage:import(inventory.name, slotNo, item.count, item) + end + end + + if type(entry.slot) == 'number' then + importSlot(entry.slot) else - debug('Invalid import source: ' .. source) + for i = 1, inventory.adapter.size() do + importSlot(i) + end end end end diff --git a/milo/plugins/inputChestTask.lua b/milo/plugins/inputChestTask.lua index ae8de01..198d1e8 100644 --- a/milo/plugins/inputChestTask.lua +++ b/milo/plugins/inputChestTask.lua @@ -1,23 +1,14 @@ local Milo = require('milo') -local device = _G.device - local InputChest = { name = 'input', priority = 10, } function InputChest:cycle(context) - for source,v in pairs(context.config.remoteDefaults) do - if v.mtype == 'input' then - local inventory = device[source] - - local list = inventory and inventory.list and inventory.list() - if list then - for slot, item in pairs(list) do - context.storage:import(source, slot, item.count, item) - end - end + for inventory in context.storage:filterActive('input') do + for slot, item in pairs(inventory.adapter.list()) do + context.storage:import(inventory.name, slot, item.count, item) end end end diff --git a/milo/plugins/limitTask.lua b/milo/plugins/limitTask.lua index ba639ce..9f66a2b 100644 --- a/milo/plugins/limitTask.lua +++ b/milo/plugins/limitTask.lua @@ -6,28 +6,19 @@ local LimitTask = { } function LimitTask:cycle(context) - local trashcan + local trashcan = context.storage:filterActive('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 - if res.limit then - local item = Milo:getItemWithQty(res, res.ignoreDamage, res.ignoreNbtHash) - if item and item.count > res.limit then - context.storage:export( - trashcan, - nil, - item.count - res.limit, - item) + if trashcan then + for _,res in pairs(context.resources) do + if res.limit then + local item = Milo:getItemWithQty(res, res.ignoreDamage, res.ignoreNbtHash) + if item and item.count > res.limit then + context.storage:export( + trashcan.name, + nil, + item.count - res.limit, + item) + end end end end diff --git a/milo/plugins/potionImportTask.lua b/milo/plugins/potionImportTask.lua index f7586dd..58a6a07 100644 --- a/milo/plugins/potionImportTask.lua +++ b/milo/plugins/potionImportTask.lua @@ -1,62 +1,61 @@ local Craft = require('turtle.craft') local Milo = require('milo') -local device = _G.device - local PotionImportTask = { name = 'potions', priority = 30, brewQueue = { }, } +local function filter(a) + return a.adapter.type == 'minecraft:brewing_stand' +end + function PotionImportTask:cycle(context) - for _, v in pairs(device) do - if v.type == 'minecraft:brewing_stand' then - if v.getBrewTime() == 0 then - local list = v.list() + for bs in context.storage:filterActive('machine', filter) do + if bs.adapter.getBrewTime() == 0 then + local list = bs.adapter.list() - if list[1] and not list[4] then - -- brewing has completd + if list[1] and not list[4] then + -- brewing has completd - if self.brewQueue[v.name] and list[1] then - local key = Milo:uniqueKey(list[1]) - if not Craft.findRecipe(key) then -debug('saving new recipe') - Milo:saveMachineRecipe(self.brewQueue[v.name], list[1], v.name) - end - end - for slot = 1, 3 do - if list[slot] then - context.storage:import(v.name, slot, 1, list[slot]) - end + if self.brewQueue[bs.name] and list[1] then + local key = Milo:uniqueKey(list[1]) + if not Craft.findRecipe(key) then + Milo:saveMachineRecipe(self.brewQueue[bs.name], list[1], bs.name) end end - self.brewQueue[v.name] = nil - - elseif not self.brewQueue[v.name] then - local recipe = { - count = 3, - ingredients = { }, - maxCount = 3, - } - local list = v.list() - - local function valid() - for i = 1, 4 do - if not list[i] then - return false - end + for slot = 1, 3 do + if list[slot] then + context.storage:import(bs.name, slot, 1, list[slot]) end - return true + end + end + self.brewQueue[bs.name] = nil + + elseif not self.brewQueue[bs.name] then + local recipe = { + count = 3, + ingredients = { }, + maxCount = 3, + } + local list = bs.adapter.list() + + local function valid() + for i = 1, 4 do + if not list[i] then + return false + end + end + return true + end + + if valid() then + for i = 1, 4 do + recipe.ingredients[i] = Milo:uniqueKey(list[i]) end - if valid() then - for i = 1, 4 do - recipe.ingredients[i] = Milo:uniqueKey(list[i]) - end - - self.brewQueue[v.name] = recipe - end + self.brewQueue[bs.name] = recipe end end end diff --git a/milo/plugins/redstoneTask.lua b/milo/plugins/redstoneTask.lua index 465902d..f1f286f 100644 --- a/milo/plugins/redstoneTask.lua +++ b/milo/plugins/redstoneTask.lua @@ -9,10 +9,10 @@ local RedstoneTask = { } function RedstoneTask:cycle(context) - for _,v in pairs(context.config.remoteDefaults) do + for v in context.storage:filterActive({ 'mtype', 'machine' }) do if v.redstone then local ri = device[v.redstone.integrator] - if not ri or not v.adapter or not v.adapter.online then + if not ri or not v.adapter then debug(v.redstone) else local function conditionsSatisfied()