diff --git a/milo/apis/milo.lua b/milo/apis/milo.lua index 1025709..6c5668e 100644 --- a/milo/apis/milo.lua +++ b/milo/apis/milo.lua @@ -74,7 +74,7 @@ function Milo:resetCraftingStatus() for _,key in pairs(Util.keys(self.context.craftingQueue)) do local item = self.context.craftingQueue[key] - if item.crafted >= item.count then + if item.crafted >= item.requested then self.context.craftingQueue[key] = nil end end @@ -193,7 +193,7 @@ end function Milo:craftAndEject(item, count) local request = self:makeRequest(item, count, function(request) -- eject rest when finished crafted - return self:eject(item, request.count) + return self:eject(item, request.requested) end) -- predict that we will eject that amount @@ -238,7 +238,7 @@ function Milo:makeRequest(item, count, callback) if request.craft > 0 then item = Util.shallowCopy(item) - item.count = request.craft + item.requested = request.craft item.callback = callback self:requestCrafting(item) end diff --git a/milo/apis/storage.lua b/milo/apis/storage.lua index ce05b5d..3cd3631 100644 --- a/milo/apis/storage.lua +++ b/milo/apis/storage.lua @@ -27,12 +27,12 @@ listCount = 0, self.localName = modem.getNameLocal() Event.on({ 'device_attach', 'device_detach' }, function(e, dev) ---_debug('%s: %s', e, tostring(dev)) +_debug('%s: %s', e, tostring(dev)) self:initStorage() end) Event.onInterval(15, function() self:showStorage() --- _debug('STORAGE: cache: %d/%d', self.hits, self.misses) + _debug('STORAGE: cache: %d/%d', self.hits, self.misses) end) end @@ -248,17 +248,8 @@ function Storage:trash(source, slot, count) end function Storage:import(source, slot, count, item) - return self:insert(slot, count, nil, item, source) -end - -function Storage:insert(slot, qty, toSlot, item, source) local total = 0 - -- toSlot is not really valid with this adapter - if toSlot then - error('Storage: toSlot is not valid') - end - local key = table.concat({ item.name, item.damage, item.nbtHash }, ':') if not self.cache then @@ -266,9 +257,9 @@ function Storage:insert(slot, qty, toSlot, item, source) end local function insert(adapter) - local amount = adapter:insert(slot, qty, toSlot, source or self.localName) + local amount = adapter:insert(slot, count, nil, source or self.localName) if amount > 0 then -_debug('INS: %s(%d): %s[%d] -> %s', +_G._debug('INS: %s(%d): %s[%d] -> %s', item.name, amount, source or self.localName, slot, adapter.name) self.dirty = true @@ -284,7 +275,7 @@ _debug('INS: %s(%d): %s[%d] -> %s', end ]] end - qty = qty - amount + count = count - amount total = total + amount end @@ -293,8 +284,8 @@ _debug('INS: %s(%d): %s[%d] -> %s', -- TODO: proper checking using ignore dmg/nbt if remote.lock == key or remote.lock == item.name then insert(remote.adapter) - if qty > 0 then -- TODO: only if void flag set - total = total + self:trash(source, slot, qty) + if count > 0 then -- TODO: only if void flag set + total = total + self:trash(source, slot, count) end return total end @@ -302,7 +293,7 @@ _debug('INS: %s(%d): %s[%d] -> %s', if self.cache[key] then -- is this item in some chest for _, adapter in self:onlineAdapters() do - if qty <= 0 then + if count <= 0 then break end if adapter.cache and adapter.cache[key] and not adapter.lock then @@ -313,7 +304,7 @@ _debug('INS: %s(%d): %s[%d] -> %s', -- high to low priority for remote in self:onlineAdapters() do - if qty <= 0 then + if count <= 0 then break end if not remote.lock then diff --git a/milo/apis/turtle/craft.lua b/milo/apis/turtle/craft.lua index 8c2dea9..c3e25ee 100644 --- a/milo/apis/turtle/craft.lua +++ b/milo/apis/turtle/craft.lua @@ -16,9 +16,9 @@ local Craft = { MACHINE_LOOKUP = 'usr/config/machine_crafting.db', } -local function clearGrid(inventoryAdapter) +local function clearGrid(storage) turtle.eachFilledSlot(function(slot) - inventoryAdapter:insert(slot.index, slot.count, nil, slot) + storage:import(storage.localName, slot.index, slot.count, slot) end) for i = 1, 16 do @@ -76,7 +76,7 @@ function Craft.sumIngredients(recipe) return t end -local function machineCraft(recipe, inventoryAdapter, machineName, request, count, item) +local function machineCraft(recipe, storage, machineName, request, count, item) local machine = device[machineName] if not machine then request.status = 'machine not found' @@ -94,7 +94,7 @@ local function machineCraft(recipe, inventoryAdapter, machineName, request, coun local xferred = { } for k,v in pairs(recipe.ingredients) do - local provided = inventoryAdapter:provide(splitKey(v), count, k, machineName) + local provided = storage:provide(splitKey(v), count, k, machineName) xferred[k] = { key = v, count = provided, @@ -103,7 +103,7 @@ local function machineCraft(recipe, inventoryAdapter, machineName, request, coun -- take back out whatever we put in for k2,v2 in pairs(xferred) do if v2.count > 0 then - inventoryAdapter:import(machineName, k2, v2.count, splitKey(v2.key)) + storage:import(machineName, k2, v2.count, splitKey(v2.key)) end end request.status = 'Invalid recipe' @@ -116,8 +116,8 @@ local function machineCraft(recipe, inventoryAdapter, machineName, request, coun item.pending[recipe.result] = count * recipe.count end -local function turtleCraft(recipe, inventoryAdapter, request, count) - if not clearGrid(inventoryAdapter) then +local function turtleCraft(recipe, storage, request, count) + if not clearGrid(storage) then request.status = 'grid in use' request.statusCode = Craft.STATUS_ERROR return @@ -125,7 +125,7 @@ local function turtleCraft(recipe, inventoryAdapter, request, count) for k,v in pairs(recipe.ingredients) do local item = splitKey(v) - if inventoryAdapter:provide(item, count, k) ~= count then + if storage:provide(item, count, k) ~= count then -- FIX: ingredients cannot be stacked request.status = 'unknown error' request.statusCode = Craft.STATUS_ERROR @@ -137,20 +137,23 @@ local function turtleCraft(recipe, inventoryAdapter, request, count) if turtle.craft() then request.crafted = request.crafted + count * recipe.count request.status = 'crafted' - request.statusCode = Craft.STATUS_INFO - return true + request.statusCode = Craft.STATUS_SUCCESS + else + request.status = 'Failed to craft' + request.statusCode = Craft.STATUS_ERROR end - request.status = 'Failed to craft' - request.statusCode = Craft.STATUS_ERROR + clearGrid(storage) + return request.statusCode == Craft.STATUS_SUCCESS end -function Craft.processPending(item, inventoryAdapter) +function Craft.processPending(item, storage) for key, count in pairs(item.pending) do - local imported = inventoryAdapter.activity[key] + local imported = storage.activity[key] if imported then local amount = math.min(imported, count) - inventoryAdapter.activity[key] = imported - amount + storage.activity[key] = imported - amount item.pending[key] = count - amount + item.ingredients[key].crafted = item.ingredients[key].crafted + amount if item.pending[key] <= 0 then item.pending[key] = nil end @@ -158,7 +161,7 @@ function Craft.processPending(item, inventoryAdapter) end end -function Craft.craftRecipe(recipe, count, inventoryAdapter, origItem) +function Craft.craftRecipe(recipe, count, storage, origItem) if type(recipe) == 'string' then recipe = Craft.recipes[recipe] if not recipe then @@ -166,11 +169,7 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter, origItem) end end - local crafted = Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) - - origItem.crafted = math.min(origItem.count, origItem.crafted + crafted) - - return crafted + return Craft.craftRecipeInternal(recipe, count, storage, origItem) end local function adjustCounts(recipe, count, ingredients) @@ -184,9 +183,15 @@ local function adjustCounts(recipe, count, ingredients) result.count = result.count + (count * recipe.count) end -function Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) +function Craft.craftRecipeInternal(recipe, count, storage, origItem) local request = origItem.ingredients[recipe.result] + if origItem.pending[recipe.result] then + request.status = 'processing' + request.statusCode = Craft.STATUS_INFO + return 0 + end + local canCraft = Craft.getCraftableAmount(recipe, count, origItem.ingredients) if not origItem.forceCrafting and canCraft == 0 then return 0 @@ -199,6 +204,8 @@ function Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) count = canCraft end +_G._debug({'eval', recipe.result, count }) + local maxCount = recipe.maxCount or math.floor(64 / recipe.count) for key,icount in pairs(Craft.sumIngredients(recipe)) do @@ -213,8 +220,9 @@ function Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) if not irecipe then return 0 end + local iqty = need - itemCount - local crafted = Craft.craftRecipeInternal(irecipe, iqty, inventoryAdapter, origItem) + local crafted = Craft.craftRecipeInternal(irecipe, iqty, storage, origItem) if not origItem.forceCrafting and crafted < iqty then return 0 end @@ -224,23 +232,16 @@ function Craft.craftRecipeInternal(recipe, count, inventoryAdapter, origItem) end end - local crafted = 0 while canCraft > 0 do - if origItem.pending[recipe.result] then - request.status = 'processing' - request.statusCode = Craft.STATUS_INFO - break - end - local batch = math.min(canCraft, maxCount) - - if Craft.machineLookup[recipe.result] then - if not machineCraft(recipe, inventoryAdapter, - Craft.machineLookup[recipe.result], request, batch, origItem) then + local machine = Craft.machineLookup[recipe.result] +_G._debug({ 'crafting', recipe.result, batch }) + if machine then + if not machineCraft(recipe, storage, machine, request, batch, origItem) then break end - elseif not turtleCraft(recipe, inventoryAdapter, request, batch) then + elseif not turtleCraft(recipe, storage, request, batch) then break end @@ -275,7 +276,7 @@ end -- determine the full list of ingredients needed to craft -- a quantity of a recipe. -function Craft.getResourceList(inRecipe, items, inCount) +function Craft.getResourceList(inRecipe, items, inCount, pending) local summed = { } local function sumItems(recipe, key, count) @@ -295,6 +296,10 @@ function Craft.getResourceList(inRecipe, items, inCount) local used = math.min(summedItem.count, total) local need = total - used + if pending and pending[key] then + need = need - pending[key] + end + if recipe.craftingTools and recipe.craftingTools[key] then summedItem.total = 1 if summedItem.count > 0 then @@ -325,8 +330,13 @@ function Craft.getResourceList(inRecipe, items, inCount) end inCount = math.ceil(inCount / inRecipe.count) - for ikey,iqty in pairs(Craft.sumIngredients(inRecipe)) do - sumItems(inRecipe, ikey, math.ceil(inCount * iqty)) + if pending and pending[inRecipe.result] then + inCount = inCount - pending[inRecipe.result] + end + if inCount > 0 then + for ikey,iqty in pairs(Craft.sumIngredients(inRecipe)) do + sumItems(inRecipe, ikey, math.ceil(inCount * iqty)) + end end return summed @@ -339,7 +349,7 @@ function Craft.getResourceList4(inRecipe, items, count) end -- given a certain quantity, return how many of those can be crafted -function Craft.getCraftableAmount(inRecipe, count, items, missing) +function Craft.getCraftableAmount(inRecipe, inCount, items, missing) local function sumItems(recipe, summedItems, count) local canCraft = 0 @@ -367,7 +377,7 @@ function Craft.getCraftableAmount(inRecipe, count, items, missing) return canCraft end - return sumItems(inRecipe, { }, math.ceil(count / inRecipe.count)) + return sumItems(inRecipe, { }, math.ceil(inCount / inRecipe.count)) end function Craft.loadRecipes() diff --git a/milo/apps/water.lua b/milo/apps/water.lua new file mode 100644 index 0000000..15fd48a --- /dev/null +++ b/milo/apps/water.lua @@ -0,0 +1,17 @@ +local os = _G.os +local turtle = _G.turtle + +while true do + turtle.placeDown('minecraft:bucket:0') + turtle.placeDown('minecraft:glass_bottle:0') + for k,v in pairs(turtle.getInventory()) do + if v.name == 'minecraft:concrete_powder' then + turtle.select(k) + for _ = 1, v.count do + turtle.placeDown() + turtle.digDown() + end + end + end + os.pullEvent('turtle_inventory') +end diff --git a/milo/plugins/craftTask.lua b/milo/plugins/craftTask.lua index ea01318..75711e0 100644 --- a/milo/plugins/craftTask.lua +++ b/milo/plugins/craftTask.lua @@ -15,10 +15,11 @@ function craftTask:craft(recipe, item) if Milo:isCraftingPaused() then return end - Craft.processPending(item, context.storage) - item.ingredients = Craft.getResourceList(recipe, Milo:listItems(), item.count - item.crafted) +--TODO: this needs to take into account what is pending + item.ingredients = Craft.getResourceList( + recipe, Milo:listItems(), item.requested - item.crafted, item.pending) for k, v in pairs(item.ingredients) do v.crafted = v.used @@ -29,24 +30,39 @@ function craftTask:craft(recipe, item) v.statusCode = Craft.STATUS_ERROR end end - item.ingredients[recipe.result] = Util.shallowCopy(item) + item.ingredients[recipe.result] = item item.ingredients[recipe.result].total = item.count item.ingredients[recipe.result].crafted = item.crafted - Craft.craftRecipe(recipe, item.count - item.crafted, context.storage, item) - Milo:clearGrid() +_G._p2 = item +if not item.history then + item.history = { } +end +local t = Util.shallowCopy(item) +t.history = { input = { }, output = { } } +for k,v in pairs(item.ingredients) do + t.history.input[k] = Util.shallowCopy(v) +end +table.insert(item.history, t) + + Craft.craftRecipe(recipe, item.requested - item.crafted, context.storage, item) + +for k,v in pairs(item.ingredients) do + t.history.output[k] = Util.shallowCopy(v) +end + end function craftTask:cycle() for _,key in pairs(Util.keys(context.craftingQueue)) do local item = context.craftingQueue[key] - if item.count - item.crafted > 0 then + if item.requested - item.crafted > 0 then local recipe = Craft.findRecipe(key) if recipe then sync(turtle, function() self:craft(recipe, item) end) - if item.callback and item.crafted >= item.count then + if item.callback and item.crafted >= item.requested then item.callback(item) -- invoke callback end elseif not context.controllerAdapter then diff --git a/milo/plugins/demandCraft.lua b/milo/plugins/demandCraft.lua index bc059dd..be09056 100644 --- a/milo/plugins/demandCraft.lua +++ b/milo/plugins/demandCraft.lua @@ -100,7 +100,7 @@ function craftPage.wizard.pages.resources:enable() local count = tonumber(self.parent.quantity.count.value) local recipe = Craft.findRecipe(craftPage.item) if recipe then - local ingredients = Craft.getResourceList(recipe, items, count) + local ingredients = Craft.getResourceList4(recipe, items, count) for _,v in pairs(ingredients) do v.displayName = itemDB:getName(v) end @@ -117,11 +117,11 @@ function craftPage:eventHandler(event) elseif event.type == 'accept' then local item = Util.shallowCopy(self.item) - item.count = tonumber(self.wizard.pages.quantity.count.value) + item.requested = tonumber(self.wizard.pages.quantity.count.value) item.forceCrafting = true if self.wizard.pages.quantity.eject.value then item.callback = function(request) - Milo:eject(item, request.count) + Milo:eject(item, request.requested) end end Milo:requestCrafting(item) diff --git a/milo/plugins/importTask.lua b/milo/plugins/importTask.lua index 4ef61b8..059ba89 100644 --- a/milo/plugins/importTask.lua +++ b/milo/plugins/importTask.lua @@ -9,22 +9,35 @@ local function filter(a) return a.imports end --- TODO: ignore damage/nbt - function ImportTask:cycle(context) for inventory in context.storage:filterActive('machine', filter) do for _, entry in pairs(inventory.imports) do + local function itemMatchesFilter(item) + if not entry.ignoreDamage and not entry.ignoreNbtHash then + return entry.filter[item.key] + end + + for key in pairs(entry.filter) do + local v = Milo:splitKey(key) + if item.name == v.name and + (entry.ignoreDamage or item.damage == v.damage) and + (entry.ignoreNbtHash or item.nbtHash == v.nbtHash) then + return true + end + 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] + return not itemMatchesFilter(item) end - return entry.filter[key] + + return itemMatchesFilter(item) end local function importSlot(slotNo) diff --git a/milo/plugins/jobMonitor.lua b/milo/plugins/jobMonitor.lua index da4fc30..53411fe 100644 --- a/milo/plugins/jobMonitor.lua +++ b/milo/plugins/jobMonitor.lua @@ -47,9 +47,8 @@ function jobMonitor:updateList(craftList) for _,v in pairs(craftList) do table.insert(t, v) v.index = #t - v.showRemaining = true - for k2,v2 in pairs(v.ingredients) do - if v2.key ~= v.key and v2.statusCode then + for k2,v2 in pairs(v.ingredients or { }) do + if v2.key ~= v.key --[[and v2.statusCode ]] then table.insert(t, v2) if not v2.displayName then v2.displayName = itemDB:getName(k2) @@ -67,12 +66,12 @@ end function jobMonitor.grid:getDisplayValues(row) row = Util.shallowCopy(row) - if row.showRemaining then - row.remaining = math.max(0, row.count - row.crafted) + if row.requested then + row.remaining = math.max(0, row.requested - row.crafted) else row.displayName = ' ' .. row.displayName end - row.progress = string.format('%d/%d', row.crafted, row.count) + --row.progress = string.format('%d/%d', row.crafted, row.count) return row end diff --git a/milo/plugins/remote.lua b/milo/plugins/remote.lua index e7100dc..d01b5b4 100644 --- a/milo/plugins/remote.lua +++ b/milo/plugins/remote.lua @@ -95,7 +95,7 @@ local function client(socket) local transferred = context.storage:export( context.localName, nil, - request.count, + request.requested, data.item) turtle.eachFilledSlot(function(slot) diff --git a/milo/plugins/replenishTask.lua b/milo/plugins/replenishTask.lua index 792043e..eb4605e 100644 --- a/milo/plugins/replenishTask.lua +++ b/milo/plugins/replenishTask.lua @@ -29,7 +29,7 @@ function ReplenishTask:cycle(context) Milo:requestCrafting({ damage = res.ignoreDamage and 0 or item.damage, nbtHash = nbtHash, - count = res.low - count, + requested = res.low - count, name = item.name, displayName = item.displayName, replenish = true, @@ -37,7 +37,7 @@ function ReplenishTask:cycle(context) else local request = context.craftingQueue[Milo:uniqueKey(item)] if request and request.replenish then - request.count = request.crafted + --request.count = request.crafted end end end