milo wip
This commit is contained in:
@@ -8,10 +8,6 @@ local turtle = _G.turtle
|
|||||||
local Milo = {
|
local Milo = {
|
||||||
RECIPES_FILE = 'usr/config/recipes.db',
|
RECIPES_FILE = 'usr/config/recipes.db',
|
||||||
RESOURCE_FILE = 'usr/config/resources.db',
|
RESOURCE_FILE = 'usr/config/resources.db',
|
||||||
|
|
||||||
STATUS_INFO = 'info',
|
|
||||||
STATUS_WARNING = 'warning',
|
|
||||||
STATUS_ERROR = 'error',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Milo:init(context)
|
function Milo:init(context)
|
||||||
@@ -26,8 +22,11 @@ function Milo:requestCrafting(item)
|
|||||||
local key = Milo:uniqueKey(item)
|
local key = Milo:uniqueKey(item)
|
||||||
|
|
||||||
if not self.context.craftingQueue[key] then
|
if not self.context.craftingQueue[key] then
|
||||||
item.processing = { }
|
item.ingredients = { }
|
||||||
item.requested = item.count
|
--[[
|
||||||
|
count = requested amount,
|
||||||
|
crafted = amount that has been crafted
|
||||||
|
]]
|
||||||
item.crafted = 0
|
item.crafted = 0
|
||||||
|
|
||||||
self.context.craftingQueue[key] = item
|
self.context.craftingQueue[key] = item
|
||||||
@@ -77,7 +76,7 @@ function Milo:resetCraftingStatus()
|
|||||||
|
|
||||||
for _,key in pairs(Util.keys(self.context.craftingQueue)) do
|
for _,key in pairs(Util.keys(self.context.craftingQueue)) do
|
||||||
local item = self.context.craftingQueue[key]
|
local item = self.context.craftingQueue[key]
|
||||||
if item.crafted >= item.requested then
|
if item.crafted >= item.count then
|
||||||
debug('removing:')
|
debug('removing:')
|
||||||
debug(item)
|
debug(item)
|
||||||
self.context.craftingQueue[key] = nil
|
self.context.craftingQueue[key] = nil
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ function NetworkedAdapter:init(args)
|
|||||||
dirty = true,
|
dirty = true,
|
||||||
listCount = 0,
|
listCount = 0,
|
||||||
activity = { },
|
activity = { },
|
||||||
|
nameArray = { },
|
||||||
}
|
}
|
||||||
Util.merge(self, defaults)
|
Util.merge(self, defaults)
|
||||||
Util.merge(self, args)
|
Util.merge(self, args)
|
||||||
@@ -29,6 +30,7 @@ listCount = 0,
|
|||||||
local adapter = InventoryAdapter.wrap({ side = k, direction = self.localName })
|
local adapter = InventoryAdapter.wrap({ side = k, direction = self.localName })
|
||||||
if adapter then
|
if adapter then
|
||||||
table.insert(self.remotes, adapter)
|
table.insert(self.remotes, adapter)
|
||||||
|
self.nameArray[adapter.direction] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -47,6 +49,7 @@ listCount = 0,
|
|||||||
return a.priority > b.priority
|
return a.priority > b.priority
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
debug(self.nameArray)
|
||||||
end
|
end
|
||||||
|
|
||||||
function NetworkedAdapter:isValid()
|
function NetworkedAdapter:isValid()
|
||||||
@@ -116,13 +119,15 @@ function NetworkedAdapter:provide(item, qty, slot, direction)
|
|||||||
for _, remote in ipairs(self.remotes) do
|
for _, remote in ipairs(self.remotes) do
|
||||||
local amount = remote:provide(item, qty, slot, direction)
|
local amount = remote:provide(item, qty, slot, direction)
|
||||||
if amount > 0 then
|
if amount > 0 then
|
||||||
debug('%s(%d): %s -> %s%s',
|
debug('EXT: %s(%d): %s -> %s%s',
|
||||||
item.name, amount, remote.side, direction or self.localName,
|
item.name, amount, remote.side, direction or self.localName,
|
||||||
slot and string.format('[%d]', slot) or '')
|
slot and string.format('[%d]', slot) or '')
|
||||||
self.dirty = true
|
self.dirty = true
|
||||||
remote.dirty = true
|
remote.dirty = true
|
||||||
local entry = self.activity[key] or 0
|
--if self.nameArray[direction or self.localName] then
|
||||||
self.activity[key] = entry + amount
|
-- local entry = self.activity[key] or 0
|
||||||
|
-- self.activity[key] = entry + amount
|
||||||
|
--end
|
||||||
end
|
end
|
||||||
qty = qty - amount
|
qty = qty - amount
|
||||||
total = total + amount
|
total = total + amount
|
||||||
@@ -168,13 +173,16 @@ function NetworkedAdapter:insert(slot, qty, toSlot, item, source)
|
|||||||
local function insert(remote)
|
local function insert(remote)
|
||||||
local amount = remote:insert(slot, qty, toSlot, source or self.direction)
|
local amount = remote:insert(slot, qty, toSlot, source or self.direction)
|
||||||
if amount > 0 then
|
if amount > 0 then
|
||||||
debug('%s(%d): %s[%d] -> %s',
|
debug('INS: %s(%d): %s[%d] -> %s',
|
||||||
item.name, amount,
|
item.name, amount,
|
||||||
source or self.localName, slot, remote.side)
|
source or self.localName, slot, remote.side)
|
||||||
self.dirty = true
|
self.dirty = true
|
||||||
remote.dirty = true
|
remote.dirty = true
|
||||||
local entry = self.activity[key] or 0
|
debug('insert: ' .. (source or self.localName))
|
||||||
self.activity[key] = entry + amount
|
--if self.nameArray[source or self.localName] then
|
||||||
|
local entry = self.activity[key] or 0
|
||||||
|
self.activity[key] = entry + amount
|
||||||
|
--end
|
||||||
end
|
end
|
||||||
qty = qty - amount
|
qty = qty - amount
|
||||||
total = total + amount
|
total = total + amount
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ local RECIPES_DIR = 'usr/etc/recipes'
|
|||||||
local USER_RECIPES = 'usr/config/recipes.db'
|
local USER_RECIPES = 'usr/config/recipes.db'
|
||||||
local MACHINE_LOOKUP = 'usr/config/machine_crafting.db'
|
local MACHINE_LOOKUP = 'usr/config/machine_crafting.db'
|
||||||
|
|
||||||
local Craft = { }
|
local Craft = {
|
||||||
|
STATUS_INFO = 'info',
|
||||||
|
STATUS_WARNING = 'warning',
|
||||||
|
STATUS_ERROR = 'error',
|
||||||
|
STATUS_SUCCESS = 'success',
|
||||||
|
}
|
||||||
|
|
||||||
local function clearGrid(inventoryAdapter)
|
local function clearGrid(inventoryAdapter)
|
||||||
turtle.eachFilledSlot(function(slot)
|
turtle.eachFilledSlot(function(slot)
|
||||||
@@ -57,11 +62,24 @@ end
|
|||||||
|
|
||||||
local function machineCraft(recipe, qty, inventoryAdapter, machineName, oitem)
|
local function machineCraft(recipe, qty, inventoryAdapter, machineName, oitem)
|
||||||
local key = recipe.result
|
local key = recipe.result
|
||||||
local request = oitem.processing[key]
|
local request = oitem.ingredients[key]
|
||||||
if request then
|
|
||||||
|
debug('requested: ' .. key)
|
||||||
|
if not request then
|
||||||
|
request = {
|
||||||
|
count = qty,
|
||||||
|
crafted = 0,
|
||||||
|
}
|
||||||
|
oitem.ingredients[recipe.result] = request
|
||||||
|
end
|
||||||
|
|
||||||
|
if request.pending then
|
||||||
request.crafted = request.crafted + (inventoryAdapter.activity[key] or 0)
|
request.crafted = request.crafted + (inventoryAdapter.activity[key] or 0)
|
||||||
if request.crafted >= request.requested then
|
debug({ request.crafted, request.count })
|
||||||
oitem.processing[key] = nil -- TODO: check...
|
if request.crafted >= request.count then
|
||||||
|
request.pending = nil -- TODO: check...
|
||||||
|
request.statusCode = Craft.STATUS_SUCCESS
|
||||||
|
request.status = nil
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
@@ -69,42 +87,50 @@ local function machineCraft(recipe, qty, inventoryAdapter, machineName, oitem)
|
|||||||
|
|
||||||
local machine = device[machineName]
|
local machine = device[machineName]
|
||||||
if not machine then
|
if not machine then
|
||||||
debug('machine not found')
|
request.status = 'machine not found'
|
||||||
oitem.processing[recipe.result] = {
|
request.statusCode = Craft.STATUS_ERROR
|
||||||
status = 'machine not found'
|
return
|
||||||
}
|
|
||||||
else
|
|
||||||
for k in pairs(recipe.ingredients) do
|
|
||||||
if machine.getItemMeta(k) then
|
|
||||||
oitem.processing[recipe.result] = {
|
|
||||||
status = 'machine in use'
|
|
||||||
}
|
|
||||||
debug('machine in use: ' .. k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
debug('processing ' .. recipe.result)
|
|
||||||
for k,v in pairs(recipe.ingredients) do
|
|
||||||
if inventoryAdapter:provide(splitKey(v), qty, k, machineName) ~= qty then
|
|
||||||
-- TODO: suck em back out
|
|
||||||
oitem.processing[recipe.result] = {
|
|
||||||
status = 'unknown error'
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
oitem.processing[recipe.result] = {
|
|
||||||
status = 'processing',
|
|
||||||
requested = qty,
|
|
||||||
crafted = 0,
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for k in pairs(recipe.ingredients) do
|
||||||
|
if machine.getItemMeta(k) then
|
||||||
|
request.status = 'machine in use'
|
||||||
|
request.statusCode = Craft.STATUS_WARNING
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
debug('processing %s %d', key, qty)
|
||||||
|
|
||||||
|
for k,v in pairs(recipe.ingredients) do
|
||||||
|
if inventoryAdapter:provide(splitKey(v), qty, k, machineName) ~= qty then
|
||||||
|
-- TODO: suck em back out
|
||||||
|
request.status = 'unknown error'
|
||||||
|
request.statusCode = Craft.STATUS_ERROR
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
request.status = 'processing'
|
||||||
|
request.statusCode = Craft.STATUS_INFO
|
||||||
|
request.pending = true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function turtleCraft(recipe, qty, inventoryAdapter, oitem)
|
local function turtleCraft(recipe, qty, inventoryAdapter, oitem)
|
||||||
if not clearGrid(inventoryAdapter) then
|
local key = recipe.result
|
||||||
oitem.processing[recipe.result] = {
|
local request = oitem.ingredients[key]
|
||||||
status = 'grid in use',
|
|
||||||
|
debug('requested: ' .. key)
|
||||||
|
if not request then
|
||||||
|
request = {
|
||||||
|
count = qty,
|
||||||
|
crafted = 0,
|
||||||
}
|
}
|
||||||
|
oitem.ingredients[recipe.result] = request
|
||||||
|
end
|
||||||
|
|
||||||
|
if not clearGrid(inventoryAdapter) then
|
||||||
|
request.status = 'grid in use'
|
||||||
|
request.statusCode = Craft.STATUS_ERROR
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -121,19 +147,19 @@ local function turtleCraft(recipe, qty, inventoryAdapter, oitem)
|
|||||||
if inventoryAdapter:provide(item, provideQty, k) ~= provideQty then
|
if inventoryAdapter:provide(item, provideQty, k) ~= provideQty then
|
||||||
-- FIX: ingredients cannot be stacked
|
-- FIX: ingredients cannot be stacked
|
||||||
--debug('failed ' .. v .. ' - ' .. provideQty)
|
--debug('failed ' .. v .. ' - ' .. provideQty)
|
||||||
oitem.processing[recipe.result] = {
|
request.status = 'unknown error'
|
||||||
status = 'unknown error',
|
request.statusCode = Craft.STATUS_ERROR
|
||||||
}
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if turtle.craft() then
|
if turtle.craft() then
|
||||||
|
request.status = nil
|
||||||
|
request.statusCode = Craft.STATUS_SUCCESS
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
oitem.processing[recipe.result] = {
|
request.status = 'failed to craft'
|
||||||
status = 'processing',
|
request.statusCode = Craft.STATUS_ERROR
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Craft.loadRecipes()
|
function Craft.loadRecipes()
|
||||||
@@ -178,8 +204,9 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter, origItem)
|
|||||||
if type(recipe) == 'string' then
|
if type(recipe) == 'string' then
|
||||||
recipe = Craft.recipes[recipe]
|
recipe = Craft.recipes[recipe]
|
||||||
if not recipe then
|
if not recipe then
|
||||||
origItem.processing[recipe.result] = {
|
origItem.ingredients[recipe.result] = {
|
||||||
status = 'no recipe',
|
status = 'no recipe',
|
||||||
|
statusCode = Craft.STATUS_ERROR,
|
||||||
}
|
}
|
||||||
return 0, 'No recipe'
|
return 0, 'No recipe'
|
||||||
end
|
end
|
||||||
@@ -187,8 +214,9 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter, origItem)
|
|||||||
|
|
||||||
local items = inventoryAdapter:listItems()
|
local items = inventoryAdapter:listItems()
|
||||||
if not items then
|
if not items then
|
||||||
origItem.processing[recipe.result] = {
|
origItem.ingredients[recipe.result] = {
|
||||||
status = 'Inventory changed',
|
status = 'Inventory changed',
|
||||||
|
statusCode = Craft.STATUS_ERROR,
|
||||||
}
|
}
|
||||||
return 0, 'Inventory changed'
|
return 0, 'Inventory changed'
|
||||||
end
|
end
|
||||||
@@ -225,7 +253,7 @@ function Craft.craftRecipe(recipe, count, inventoryAdapter, origItem)
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if not turtleCraft(recipe, requested, inventoryAdapter) then
|
if not turtleCraft(recipe, requested, inventoryAdapter, origItem) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,13 +12,7 @@ local craftTask = {
|
|||||||
|
|
||||||
-- Craft
|
-- Craft
|
||||||
function craftTask:craftItem(recipe, originalItem, count)
|
function craftTask:craftItem(recipe, originalItem, count)
|
||||||
local missing = { }
|
local toCraft = Craft.getCraftableAmount(recipe, count, Milo:listItems(), { })
|
||||||
local toCraft = Craft.getCraftableAmount(recipe, count, Milo:listItems(), missing)
|
|
||||||
if missing.name then
|
|
||||||
originalItem.status = string.format('%s missing', itemDB:getName(missing.name))
|
|
||||||
originalItem.statusCode = Milo.STATUS_WARNING
|
|
||||||
end
|
|
||||||
|
|
||||||
local crafted = 0
|
local crafted = 0
|
||||||
|
|
||||||
if toCraft > 0 then
|
if toCraft > 0 then
|
||||||
@@ -99,23 +93,15 @@ end
|
|||||||
function craftTask:craft(recipe, item)
|
function craftTask:craft(recipe, item)
|
||||||
item.status = nil
|
item.status = nil
|
||||||
item.statusCode = nil
|
item.statusCode = nil
|
||||||
item.crafted = 0
|
|
||||||
|
|
||||||
if Milo:isCraftingPaused() then
|
if Milo:isCraftingPaused() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- todo: is this needed ?
|
|
||||||
if not Milo:clearGrid() then
|
|
||||||
item.status = 'Grid obstructed'
|
|
||||||
item.statusCode = Milo.STATUS_ERROR
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if item.forceCrafting then
|
if item.forceCrafting then
|
||||||
item.crafted = self:forceCraftItem(recipe, item, item.count)
|
item.crafted = item.crafted + self:forceCraftItem(recipe, item, item.count - item.crafted)
|
||||||
else
|
else
|
||||||
item.crafted = self:craftItem(recipe, item, item.count)
|
item.crafted = item.crafted + self:craftItem(recipe, item, item.count - item.crafted)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -126,12 +112,12 @@ function craftTask:cycle()
|
|||||||
local recipe = Craft.recipes[key]
|
local recipe = Craft.recipes[key]
|
||||||
if recipe then
|
if recipe then
|
||||||
self:craft(recipe, item)
|
self:craft(recipe, item)
|
||||||
if item.eject and item.crafted >= item.requested then
|
if item.eject and item.crafted >= item.count then
|
||||||
Milo:eject(item, item.requested)
|
Milo:eject(item, item.count)
|
||||||
end
|
end
|
||||||
elseif not context.controllerAdapter then
|
elseif not context.controllerAdapter then
|
||||||
item.status = '(no recipe)'
|
item.status = '(no recipe)'
|
||||||
item.statusCode = Milo.STATUS_ERROR
|
item.statusCode = Craft.STATUS_ERROR
|
||||||
item.crafted = 0
|
item.crafted = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,28 +1,30 @@
|
|||||||
|
local Craft = require('turtle.craft')
|
||||||
|
local itemDB = require('itemDB')
|
||||||
local Milo = require('milo')
|
local Milo = require('milo')
|
||||||
local Peripheral = require('peripheral')
|
local Peripheral = require('peripheral')
|
||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
local colors = _G.colors
|
local colors = _G.colors
|
||||||
|
|
||||||
local context = Milo:getContext()
|
local context = Milo:getContext()
|
||||||
local mon = Peripheral.lookup(context.config.monitor) or
|
local mon = Peripheral.lookup(context.config.monitor) or
|
||||||
error('Monitor is not attached')
|
error('Monitor is not attached')
|
||||||
local display = UI.Device {
|
|
||||||
device = mon,
|
|
||||||
textScale = .5,
|
|
||||||
}
|
|
||||||
|
|
||||||
local jobList = UI.Page {
|
local jobList = UI.Page {
|
||||||
parent = display,
|
parent = UI.Device {
|
||||||
|
device = mon,
|
||||||
|
textScale = .5,
|
||||||
|
},
|
||||||
grid = UI.Grid {
|
grid = UI.Grid {
|
||||||
sortColumn = 'index',
|
sortColumn = 'index',
|
||||||
backgroundFocusColor = colors.black,
|
backgroundFocusColor = colors.black,
|
||||||
columns = {
|
columns = {
|
||||||
{ heading = 'Qty', key = 'count', width = 6 },
|
{ heading = 'Qty', key = 'remaining', width = 6 },
|
||||||
{ heading = 'Crafting', key = 'displayName', }, -- width = display.width / 2 - 10 },
|
{ heading = 'Crafting', key = 'displayName', },
|
||||||
{ heading = 'Status', key = 'status', }, -- width = display.width - 10 },
|
{ heading = 'Status', key = 'status', },
|
||||||
{ heading = 'Req', key = 'requested', width = 6 },
|
{ heading = 'Req', key = 'count', width = 3 },
|
||||||
{ heading = 'Cra', key = 'crafted', width = 6 },
|
{ heading = 'Cra', key = 'crafted', width = 3 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -36,16 +38,16 @@ end
|
|||||||
function jobList:updateList(craftList)
|
function jobList:updateList(craftList)
|
||||||
if not Milo:isCraftingPaused() then
|
if not Milo:isCraftingPaused() then
|
||||||
local t = { }
|
local t = { }
|
||||||
local index = 1
|
for _,v in pairs(craftList) do
|
||||||
for k,v in pairs(craftList) do
|
table.insert(t, v)
|
||||||
t[k] = v
|
v.index = #t
|
||||||
v.index = index
|
v.showRemining = true
|
||||||
index = index + 1
|
for k2,v2 in pairs(v.ingredients) do
|
||||||
for k2,v2 in pairs(v.processing) do
|
table.insert(t, v2)
|
||||||
t[k2] = v2
|
if not v2.displayName then
|
||||||
v2.displayName = k2
|
v2.displayName = itemDB:getName(k2)
|
||||||
v2.index = index
|
end
|
||||||
index = index + 1
|
v2.index = #t
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.grid:setValues(t)
|
self.grid:setValues(t)
|
||||||
@@ -55,15 +57,23 @@ function jobList:updateList(craftList)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function jobList.grid:getRowTextColor(row, selected)
|
function jobList.grid:getDisplayValues(row)
|
||||||
if row.statusCode == Milo.STATUS_ERROR then
|
row = Util.shallowCopy(row)
|
||||||
return colors.red
|
if row.showRemining then
|
||||||
elseif row.statusCode == Milo.STATUS_WARNING then
|
row.remaining = row.count - row.crafted
|
||||||
return colors.yellow
|
|
||||||
elseif row.statusCode == Milo.STATUS_INFO then
|
|
||||||
return colors.lime
|
|
||||||
end
|
end
|
||||||
return UI.Grid:getRowTextColor(row, selected)
|
return row
|
||||||
|
end
|
||||||
|
|
||||||
|
function jobList.grid:getRowTextColor(row, selected)
|
||||||
|
local statusColor = {
|
||||||
|
[ Craft.STATUS_ERROR ] = colors.red,
|
||||||
|
[ Craft.STATUS_WARNING ] = colors.orange,
|
||||||
|
[ Craft.STATUS_INFO ] = colors.yellow,
|
||||||
|
[ Craft.STATUS_SUCCESS ] = colors.green,
|
||||||
|
}
|
||||||
|
return row.statusCode and statusColor[row.statusCode] or
|
||||||
|
UI.Grid:getRowTextColor(row, selected)
|
||||||
end
|
end
|
||||||
|
|
||||||
jobList:enable()
|
jobList:enable()
|
||||||
|
|||||||
Reference in New Issue
Block a user