From 1c30ccda29b53755d3dac486f00629647c517704 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Wed, 3 Apr 2019 17:13:20 -0400 Subject: [PATCH] milo: improve export speed --- milo/apis/craft2.lua | 6 +- milo/apis/storage.lua | 19 ++++-- milo/plugins/exportTask.lua | 120 +++++++++++++++++++----------------- 3 files changed, 82 insertions(+), 63 deletions(-) diff --git a/milo/apis/craft2.lua b/milo/apis/craft2.lua index 765b4e9..5203052 100644 --- a/milo/apis/craft2.lua +++ b/milo/apis/craft2.lua @@ -1,8 +1,9 @@ local itemDB = require('core.itemDB') local Util = require('util') -local fs = _G.fs -local turtle = _G.turtle +local fs = _G.fs +local parallel = _G.parallel +local turtle = _G.turtle local Craft = { STATUS_INFO = 'info', @@ -147,6 +148,7 @@ local function turtleCraft(recipe, storage, request, count) parallel.waitForAll(table.unpack(fns)) if failed then + Craft.clearGrid(storage) return end diff --git a/milo/apis/storage.lua b/milo/apis/storage.lua index ffa3ad4..3844d05 100644 --- a/milo/apis/storage.lua +++ b/milo/apis/storage.lua @@ -412,12 +412,18 @@ function Storage:export(target, slot, count, item) local total = 0 local key = item.key or table.concat({ item.name, item.damage, item.nbtHash }, ':') - local function provide(adapter) - local amount = rawExport(adapter, target.adapter, item, count, slot) + local function provide(adapter, pcount) + -- update cache before export to allow for simultaneous calls + self:updateCache(adapter, item, -pcount) + + local amount = rawExport(adapter, target.adapter, item, pcount, slot) + + if amount ~= pcount then + -- this *should* only happen if cache is out of sync + self:updateCache(adapter, item, pcount - amount) + end if amount > 0 then - self:updateCache(adapter, item, -amount) - _G._debug('EXT: %s(%d): %s -> %s%s in %s', item.displayName or item.name, amount, self:_sn(adapter.name), self:_sn(target.name), slot and string.format('[%d]', slot) or '[*]', Util.round(timer(), 2)) @@ -428,8 +434,9 @@ function Storage:export(target, slot, count, item) -- request from adapters with this item for _, adapter in self:onlineAdapters() do - if adapter.cache and adapter.cache[key] then - provide(adapter) + local cache = adapter.cache and adapter.cache[key] + if cache then + provide(adapter, math.min(count, cache.count)) if count <= 0 then return total end diff --git a/milo/plugins/exportTask.lua b/milo/plugins/exportTask.lua index 5114f30..dd791a3 100644 --- a/milo/plugins/exportTask.lua +++ b/milo/plugins/exportTask.lua @@ -1,6 +1,8 @@ local itemDB = require('core.itemDB') local Milo = require('milo') +local parallel = _G.parallel + local ExportTask = { name = 'exporter', priority = 40, @@ -11,77 +13,85 @@ local function filter(a) end function ExportTask:cycle(context) + local tasks = { } + for node in context.storage:filterActive('machine', filter) do - local s, m = pcall(function() - for _, entry in pairs(node.exports) do + table.insert(tasks, function() + local s, m = pcall(function() + for _, entry in pairs(node.exports) do - if not entry.filter then - -- exports must have a filter - -- TODO: validate in exportView - break - end - - local function exportSingleSlot() - local slot = node.adapter.getItemMeta(entry.slot) - - if slot and slot.count == slot.maxCount then - return + if not entry.filter then + -- exports must have a filter + -- TODO: validate in exportView + break end - if slot then - -- something is in the slot, find what we can export - for key in pairs(entry.filter) do - local filterItem = itemDB:splitKey(key) - if (slot.name == filterItem.name and - (entry.ignoreDamage or slot.damage == filterItem.damage) and - (entry.ignoreNbtHash or slot.nbtHash == filterItem.nbtHash)) then + local function exportSingleSlot() + local slot = node.adapter.getItemMeta(entry.slot) - local items = Milo:getMatches(filterItem, entry) - local _, item = next(items) - if item then - local count = math.min(item.count, slot.maxCount - slot.count) - context.storage:export(node, entry.slot, count, item) + if slot and slot.count == slot.maxCount then + return + end + + if slot then + -- something is in the slot, find what we can export + for key in pairs(entry.filter) do + local filterItem = itemDB:splitKey(key) + if (slot.name == filterItem.name and + (entry.ignoreDamage or slot.damage == filterItem.damage) and + (entry.ignoreNbtHash or slot.nbtHash == filterItem.nbtHash)) then + + local items = Milo:getMatches(filterItem, entry) + local _, item = next(items) + if item then + local count = math.min(item.count, slot.maxCount - slot.count) + context.storage:export(node, entry.slot, count, item) + end + break end - break end + return end - return - end - -- slot is empty - export first matching item we have in storage - for key in pairs(entry.filter) do - local items = Milo:getMatches(itemDB:splitKey(key), entry) - local _, item = next(items) - if item then - local count = math.min(item.count, itemDB:getMaxCount(item)) - context.storage:export(node, entry.slot, count, item) - break - end - end - end - - local function exportItems() - for key in pairs(entry.filter) do - local items = Milo:getMatches(itemDB:splitKey(key), entry) - for _,item in pairs(items) do - if context.storage:export(node, nil, item.count, item) == 0 then - -- TODO: really shouldn't break here as there may be room in other slots - -- leaving for now for performance reasons + -- slot is empty - export first matching item we have in storage + for key in pairs(entry.filter) do + local items = Milo:getMatches(itemDB:splitKey(key), entry) + local _, item = next(items) + if item then + local count = math.min(item.count, itemDB:getMaxCount(item)) + context.storage:export(node, entry.slot, count, item) break end end end + + local function exportItems() + for key in pairs(entry.filter) do + local items = Milo:getMatches(itemDB:splitKey(key), entry) + for _,item in pairs(items) do + if context.storage:export(node, nil, item.count, item) == 0 then + -- TODO: really shouldn't break here as there may be room in other slots + -- leaving for now for performance reasons + break + end + end + end + end + if type(entry.slot) == 'number' then + exportSingleSlot() + else + exportItems() + end end - if type(entry.slot) == 'number' then - exportSingleSlot() - else - exportItems() - end + end) + + if not s and m then + _G._debug('EXPORTER error: ' .. m) end end) - if not s and m then - _G._debug('EXPORTER error: ' .. m) - end + end + if #tasks > 0 then + parallel.waitForAll(table.unpack(tasks)) end end