rework milo crafting

This commit is contained in:
kepler155c
2018-11-10 21:01:53 -05:00
parent aff05f8587
commit bc9028f0c7
10 changed files with 131 additions and 85 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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()

17
milo/apps/water.lua Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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