autocrafting improvements

This commit is contained in:
kepler155c
2018-01-10 16:48:23 -05:00
parent d4cf76b8e8
commit f7893ab2fe
24 changed files with 1798 additions and 159 deletions

View File

@@ -23,13 +23,13 @@ local turtle = _G.turtle
multishell.setTitle(multishell.getCurrent(), 'Resource Manager')
local config = {
computerFacing = 'north',
computerFacing = 'north', -- direction turtle is facing
inventory = 'back',
craftingChest = 'top',
inventory = 'top',
craftingChest = 'bottom',
controller = 'none',
trashDirection = 'up', -- trash /chest in relation to chest
trashDirection = 'up', -- trash/chest in relation to inventory
monitor = 'type/monitor',
}
@@ -49,7 +49,6 @@ if device.workbench then
[ 'left' ] = 'right',
[ 'right' ] = 'left',
}
local duckAntennaSide = oppositeSide[device.workbench.side]
duckAntenna = peripheral.wrap(duckAntennaSide)
if not duckAntenna or not duckAntenna.getAllStacks then
@@ -57,11 +56,16 @@ if device.workbench then
end
end
local STATUS_INFO = 'info'
local STATUS_WARNING = 'warning'
local STATUS_ERROR = 'error'
local RESOURCE_FILE = 'usr/config/resources.db'
local RECIPES_FILE = 'usr/config/recipes.db'
local craftingPaused = false
local canCraft = not not duckAntenna or turtleChestAdapter
local canCraft = not not (turtle and turtle.craft)
local canLearn = not not duckAntenna or not not turtleChestAdapter
local userRecipes = Util.readTable(RECIPES_FILE) or { }
local jobList
local resources
@@ -188,6 +192,7 @@ local function addCraftingRequest(item, craftList, count)
craftList[key] = request
end
request.count = request.count + count
return request
end
local function craftItem(recipe, items, originalItem, craftList, count)
@@ -199,6 +204,7 @@ local function craftItem(recipe, items, originalItem, craftList, count)
if not isGridClear() then
if not clearGrid() then
originalItem.status = 'Grid obstructed'
originalItem.statusCode = STATUS_ERROR
return 0
end
end
@@ -207,7 +213,7 @@ local function craftItem(recipe, items, originalItem, craftList, count)
local toCraft = Craft.getCraftableAmount(recipe, count, items, missing)
if missing.name then
originalItem.status = string.format('%s missing', itemDB:getName(missing.name))
originalItem.statusCode = 'missing'
originalItem.statusCode = STATUS_WARNING
end
local crafted = 0
@@ -222,9 +228,15 @@ local function craftItem(recipe, items, originalItem, craftList, count)
if count > 0 and items then
local ingredients = Craft.getResourceList4(recipe, items, count)
for _,ingredient in pairs(ingredients) do
--if not ingredient.recipe and ingredient.count < 0 then
if ingredient.need > 0 then
addCraftingRequest(ingredient, craftList, ingredient.need)
local item = addCraftingRequest(ingredient, craftList, ingredient.need)
if Craft.findRecipe(item) then
item.status = string.format('%s missing', itemDB:getName(ingredient))
item.statusCode = STATUS_WARNING
else
item.status = 'no recipe'
item.statusCode = STATUS_ERROR
end
end
end
end
@@ -278,7 +290,6 @@ local function forceCraftItem(inRecipe, items, originalItem, craftList, inCount)
local c = sumItems(summedItem.recipe, need) -- 4
craftable = math.min(craftable, math.floor((used + c) / iqty))
summedItem.craftable = summedItem.craftable + c
end
end
end
@@ -296,9 +307,14 @@ local function forceCraftItem(inRecipe, items, originalItem, craftList, inCount)
if count < inCount then
for _,ingredient in pairs(summed) do
if ingredient.need > 0 then
addCraftingRequest(ingredient, craftList, ingredient.need)
originalItem.status = string.format('%s missing', itemDB:getName(ingredient))
originalItem.statusCode = 'missing'
local item = addCraftingRequest(ingredient, craftList, ingredient.need)
if Craft.findRecipe(item) then
item.status = string.format('%s missing', itemDB:getName(ingredient))
item.statusCode = STATUS_WARNING
else
item.status = '(no recipe)'
item.statusCode = STATUS_ERROR
end
end
end
end
@@ -306,43 +322,59 @@ local function forceCraftItem(inRecipe, items, originalItem, craftList, inCount)
end
local function craftItems(craftList, allItems)
for _,key in pairs(Util.keys(craftList)) do
local item = craftList[key]
local recipe = Craft.recipes[key]
if recipe then
item.status = nil
item.statusCode = nil
if item.forceCrafting then
item.crafted = forceCraftItem(recipe, allItems, item, craftList, item.count)
else
item.crafted = craftItem(recipe, allItems, item, craftList, item.count)
-- turtle crafting
if canCraft then
for _,key in pairs(Util.keys(craftList)) do
local item = craftList[key]
local recipe = Craft.recipes[key]
if recipe then
item.status = nil
item.statusCode = nil
if item.forceCrafting then
item.crafted = forceCraftItem(recipe, allItems, item, craftList, item.count)
else
item.crafted = craftItem(recipe, allItems, item, craftList, item.count)
end
allItems = listItems() -- refresh counts
if not allItems then
break
end
elseif not controllerAdapter then
item.status = '(no recipe)'
item.statusCode = STATUS_ERROR
end
allItems = listItems() -- refresh counts
if not allItems then
break
end
elseif item.rsControl then
item.status = 'Activated'
end
end
for key,item in pairs(craftList) do
if not Craft.recipes[key] and not item.rsControl then
if not controllerAdapter then
item.status = '(no recipe)'
else
-- redstone control
for _,item in pairs(craftList) do
if item.rsControl then
item.status = '(activated)'
item.statusCode = STATUS_INFO
end
end
-- controller
if controllerAdapter then
for key,item in pairs(craftList) do
if not Craft.recipes[key] and not item.rsControl then
if controllerAdapter:isCrafting(item) then
item.status = '(crafting)'
item.statusCode = STATUS_INFO
else
local count = item.count
while count >= 1 do -- try to request smaller quantities until successful
local s = pcall(function()
item.status = '(no recipe)'
item.statusCode = STATUS_ERROR
if not controllerAdapter:craft(item, count) then
item.status = '(missing ingredients)'
item.statusCode = STATUS_WARNING
error('failed')
end
item.status = '(crafting)'
item.statusCode = STATUS_INFO
end)
if s then
break -- successfully requested crafting
@@ -353,6 +385,15 @@ local function craftItems(craftList, allItems)
end
end
end
if not controllerAdapter and not canCraft then
for _,item in pairs(craftList) do
if not item.rsControl then
item.status = 'Invalid setup'
item.statusCode = STATUS_INFO
end
end
end
end
local function jobMonitor()
@@ -395,11 +436,11 @@ local function jobMonitor()
end
function jobList.grid:getRowTextColor(row, selected)
if row.status == '(no recipe)' then
if row.statusCode == STATUS_ERROR then
return colors.red
elseif row.statusCode == 'missing' then
elseif row.statusCode == STATUS_WARNING then
return colors.yellow
elseif row.statusCode == 'success' then
elseif row.statusCode == STATUS_INFO then
return colors.lime
end
return UI.Grid:getRowTextColor(row, selected)
@@ -580,12 +621,14 @@ local itemPage = UI.Page {
},
help = 'Ignore NBT of item'
},
--[[
[6] = UI.Button {
x = 2, y = -2, width = 10,
formLabel = 'Redstone',
event = 'show_rs',
text = 'Configure',
},
]]
infoButton = UI.Button {
x = 2, y = -2,
event = 'show_info',
@@ -779,10 +822,10 @@ local listingPage = UI.Page {
grid = UI.Grid {
y = 2, ey = -2,
columns = {
{ heading = 'Name', key = 'displayName' , width = 22 },
{ heading = 'Qty', key = 'count' , width = 5 },
{ heading = 'Min', key = 'low' , width = 4 },
{ heading = 'Max', key = 'limit' , width = 4 },
{ heading = 'Name', key = 'displayName' },
{ heading = 'Qty', key = 'count' , width = 4 },
{ heading = 'Min', key = 'low' , width = 4 },
{ heading = 'Max', key = 'limit' , width = 4 },
},
sortColumn = 'displayName',
},
@@ -802,6 +845,7 @@ local listingPage = UI.Page {
text = 'A',
},
},
notification = UI.Notification(),
accelerators = {
r = 'refresh',
q = 'quit',
@@ -864,10 +908,18 @@ function listingPage:eventHandler(event)
self.grid:draw()
elseif event.type == 'learn' then
UI:setPage('learn')
if canLearn then
UI:setPage('learn')
else
self.notification:error('Missing a crafting chest\nCheck configuration')
end
elseif event.type == 'craft' or event.type == 'grid_select_right' then
UI:setPage('craft', self.grid:getSelected())
if Craft.findRecipe(self.grid:getSelected()) then
UI:setPage('craft', self.grid:getSelected())
else
self.notification:error('No recipe defined')
end
elseif event.type == 'forget' then
local item = self.grid:getSelected()
@@ -885,7 +937,7 @@ function listingPage:eventHandler(event)
saveResources()
end
self.statusBar:timedStatus('Forgot: ' .. item.name, 3)
self.notification:info('Forgot: ' .. item.name)
self:refresh()
self.grid:draw()
end
@@ -957,7 +1009,7 @@ local function learnRecipe(page)
local ingredients = getTurtleInventory()
if ingredients then
turtle.select(1)
if canCraft and turtle.craft() then
if canLearn and turtle.craft() then
local results = getTurtleInventory()
if results and results[1] then
clearGrid()
@@ -1029,7 +1081,7 @@ local function learnRecipe(page)
local displayName = itemDB:getName(recipe)
listingPage.statusBar.filter:setValue(displayName)
listingPage.statusBar:timedStatus('Learned: ' .. displayName, 3)
listingPage.notification:success('Learned: ' .. displayName)
listingPage.filter = displayName
listingPage:refresh()
listingPage.grid:draw()
@@ -1037,10 +1089,10 @@ local function learnRecipe(page)
return true
end
else
page.statusBar:timedStatus('Failed to craft', 3)
listingPage.notification:error('Failed to craft', 3)
end
else
page.statusBar:timedStatus('No recipe defined', 3)
listingPage.notification:error('No recipe defined', 3)
end
end
@@ -1208,7 +1260,9 @@ function craftPage:eventHandler(event)
end
loadResources()
clearGrid()
if canCraft then
clearGrid()
end
UI:setPages({
listing = listingPage,

View File

@@ -19,7 +19,7 @@ multishell.setTitle(multishell.getCurrent(), 'Crafter')
local config = {
computerFacing = 'north',
monitor = 'monitor',
monitor = 'type/monitor',
}
Config.load('crafter', config)

50
apps/namedb.lua Normal file
View File

@@ -0,0 +1,50 @@
_G.requireInjector()
local itemDB = require('itemDB')
local json = require('json')
local Util = require('util')
local args = { ... }
local mod = args[1] or error('Syntax: namedb MOD')
--[[
"double_plant": {
"name": ["Sunflower",
"Lilac",
"Double Tallgrass",
"Large Fern",
"Rose Bush",
"Peony"],
},
--]]
local list = { }
for _,v in pairs(itemDB.data) do
local t = Util.split(v.name, '(.-):')
if t[1] == mod then
local name = t[2]
local damage = v.damage or 0
local entry = list[name]
if not entry then
entry = { }
list[name] = entry
end
if not entry.name and damage == 0 then
entry.name = v.displayName
else
if not entry.name then
entry.name = { }
elseif type(entry.name) == 'string' then
entry.name = { entry.name }
end
while #entry.name < damage do
entry.name[#entry.name + 1] = ''
end
entry.name[damage + 1] = v.displayName
end
end
end
json.encodeToFile(string.format('usr/etc/names/%s.json', mod), list)

View File

@@ -14,15 +14,17 @@ local version = "Version 1.1.6"
-- Original code by Bomb Bloke
-- Modified to integrate with opus os
requireInjector(getfenv(1))
_G.requireInjector()
local Util = require('util')
local multishell = _ENV.multishell
local os = _G.os
local recTerm, oldTerm, arg, showInput, skipLast, lastDelay, curInput = {}, Util.shallowCopy(multishell.term), {...}, false, false, 2, ""
local curBlink, oldBlink, tTerm, buffer, colourNum, xPos, yPos, oldXPos, oldYPos, tCol, bCol, xSize, ySize = false, false, {}, {}, {}, 1, 1, 1, 1, colours.white, colours.black, oldTerm.getSize()
local greys, buttons = {["0"] = true, ["7"] = true, ["8"] = true, ["f"] = true}, {"l", "r", "m"}
local charW, charH, chars, resp
local filename
local calls = { }
local curCalls = { delay = 0 }
@@ -39,7 +41,7 @@ end
for i = #arg, 1, -1 do
local curArg = arg[i]:lower()
if curArg == "-i" then
showInput, ySize = true, ySize + 1
table.remove(arg, i)
@@ -108,23 +110,23 @@ end
local function safeString(text)
local newText = {}
for i = 1, #text do
local val = text:byte(i)
newText[i] = (val > 31 and val < 127) and val or 63
end
return string.char(unpack(newText))
end
local function safeCol(text, subst)
local newText = {}
for i = 1, #text do
local val = text:sub(i, i)
newText[i] = greys[val] and val or subst
end
return table.concat(newText)
end
@@ -147,7 +149,7 @@ end
local tabId = multishell.getCurrent()
multishell.addHotkey('control-p', function()
_G.device.keyboard.addHotkey('control-p', function()
os.queueEvent('recorder_stop')
end)
@@ -185,7 +187,7 @@ while true do
end
end
multishell.removeHotkey('control-p')
_G.device.keyboard.removeHotkey('control-p')
for k,fn in pairs(oldTerm) do
multishell.term[k] = fn
@@ -206,18 +208,18 @@ print(string.format("Encoding %d frames...", #calls))
do
local callListCount, tempCalls, blink, oldBlink, curBlink, blinkDelay = 1, {}, false, false, true, 0
for i = 1, #calls - 1 do
curCalls = calls[i]
tempCalls[callListCount] = curCalls
for j = 1, #curCalls do if curCalls[j][1] == "setCursorBlink" then blink = curCalls[j][2] end end
if blink then
if blinkDelay == 0 then
curCalls[#curCalls + 1] = {"toggleCur", curBlink}
blinkDelay, curBlink = 0.4, not curBlink
end
while tempCalls[callListCount].delay > blinkDelay do
local remainder = tempCalls[callListCount].delay - blinkDelay
tempCalls[callListCount].delay = blinkDelay
@@ -225,19 +227,19 @@ do
tempCalls[callListCount] = {{"toggleCur", curBlink}, ["delay"] = remainder}
blinkDelay, curBlink = 0.4, not curBlink
end
blinkDelay = blinkDelay - tempCalls[callListCount].delay
else
if oldBlink then curCalls[#curCalls + 1] = {"toggleCur", false} end
blinkDelay = (curCalls.delay - blinkDelay) % 0.4
end
callListCount, oldBlink = callListCount + 1, blink
end
tempCalls[callListCount] = calls[#calls]
tempCalls[callListCount][#tempCalls[callListCount] + 1] = {"toggleCur", false}
calls, curCalls = tempCalls, nil
end
@@ -298,33 +300,33 @@ if showInput then for x = 1, xSize do buffer[ySize][x][3] = colourNum[colours.li
tTerm.blit = function(text, fgCol, bgCol)
if xPos > xSize or xPos + #text - 1 < 1 or yPos < 1 or yPos > ySize then return end
if not _HOST then text = safeString(text) end
if not term.isColour() then
fgCol = safeCol(fgCol, "0")
bgCol = safeCol(bgCol, "f")
end
if xPos < 1 then
text = text:sub(2 - xPos)
fgCol = fgCol:sub(2 - xPos)
bgCol = bgCol:sub(2 - xPos)
xPos = 1
end
if xPos + #text - 1 > xSize then
text = text:sub(1, xSize - xPos + 1)
fgCol = fgCol:sub(1, xSize - xPos + 1)
bgCol = bgCol:sub(1, xSize - xPos + 1)
end
for x = 1, #text do
buffer[yPos][xPos + x - 1][1] = text:sub(x, x)
buffer[yPos][xPos + x - 1][2] = fgCol:sub(x, x)
buffer[yPos][xPos + x - 1][3] = bgCol:sub(x, x)
end
xPos = xPos + #text
end
@@ -335,21 +337,21 @@ end
tTerm.clearLine = function()
local oldXPos = xPos
xPos = 1
tTerm.write(string.rep(" ", xSize))
xPos = oldXPos
end
tTerm.clear = function()
local oldXPos, oldYPos = xPos, yPos
for y = 1, ySize do
xPos, yPos = 1, y
tTerm.write(string.rep(" ", xSize))
end
xPos, yPos = oldXPos, oldYPos
end
@@ -376,7 +378,7 @@ end
tTerm.scroll = function(lines)
if math.abs(lines) < ySize then
local oldXPos, oldYPos = xPos, yPos
for y = 1, ySize do
if y + lines > 0 and y + lines <= ySize then
for x = 1, xSize do
@@ -388,7 +390,7 @@ tTerm.scroll = function(lines)
tTerm.clearLine()
end
end
xPos, yPos = oldXPos, oldYPos
else tTerm.clear() end
end
@@ -400,12 +402,12 @@ end
tTerm.newInput = function(input)
local oldTC, oldBC, oldX, oldY = tCol, bCol, xPos, yPos
tCol, bCol, xPos, yPos, ySize, input = colours.grey, colours.lightGrey, 1, ySize + 1, ySize + 1, input .. " "
while #curInput + #input + 1 > xSize do curInput = curInput:sub(curInput:find(" ") + 1) end
curInput = curInput .. input .. " "
tTerm.clearLine()
tTerm.write(curInput)
tCol, bCol, xPos, yPos, ySize = oldTC, oldBC, oldX, oldY, ySize - 1
end
@@ -422,18 +424,18 @@ local image = {["width"] = xSize * charW, ["height"] = ySize * charH}
for i = 1, #calls do
local xMin, yMin, xMax, yMax, oldBuffer, curCalls, changed = xSize + 1, ySize + 1, 0, 0, {}, calls[i], false
calls[i] = nil
for y = 1, ySize do
oldBuffer[y] = {}
for x = 1, xSize do oldBuffer[y][x] = {buffer[y][x][1], buffer[y][x][2], buffer[y][x][3], buffer[y][x][4]} end
end
snooze()
if showInput then ySize = ySize - 1 end
for j = 1, #curCalls do if tTerm[curCalls[j][1]] then tTerm[curCalls[j][1]](unpack(curCalls[j], 2)) end end
if showInput then ySize = ySize + 1 end
if i > 1 then
for yy = 1, ySize do for xx = 1, xSize do if buffer[yy][xx][1] ~= oldBuffer[yy][xx][1] or (buffer[yy][xx][2] ~= oldBuffer[yy][xx][2] and buffer[yy][xx][1] ~= " ") or buffer[yy][xx][3] ~= oldBuffer[yy][xx][3] then
changed = true
@@ -443,7 +445,7 @@ for i = 1, #calls do
if yy > yMax then yMax = yy end
end end end
else xMin, yMin, xMax, yMax, changed = 1, 1, xSize, ySize, true end
if oldBlink and (xPos ~= oldXPos or yPos ~= oldYPos or not curBlink) and oldXPos > 0 and oldYPos > 0 and oldXPos <= xSize and oldYPos <= ySize then
changed = true
if oldXPos < xMin then xMin = oldXPos end
@@ -452,7 +454,7 @@ for i = 1, #calls do
if oldYPos > yMax then yMax = oldYPos end
buffer[oldYPos][oldXPos][4] = false
end
if curBlink and (xPos ~= oldXPos or yPos ~= oldYPos or not oldBlink) and xPos > 0 and yPos > 0 and xPos <= xSize and yPos <= ySize then
changed = true
if xPos < xMin then xMin = xPos end
@@ -461,9 +463,9 @@ for i = 1, #calls do
if yPos > yMax then yMax = yPos end
buffer[yPos][xPos][4] = true
end
oldBlink, oldXPos, oldYPos = curBlink, xPos, yPos
local thisFrame = {
["xstart"] = (xMin - 1) * charW,
["ystart"] = (yMin - 1) * charH,
@@ -472,18 +474,18 @@ for i = 1, #calls do
["delay"] = curCalls.delay,
["disposal"] = 1
}
for y = 1, (yMax - yMin + 1) * charH do
local row = {}
for x = 1, (xMax - xMin + 1) * charW do row[x] = " " end
thisFrame[y] = row
end
snooze()
for yy = yMin, yMax do
local yBump = (yy - yMin) * charH
for xx = xMin, xMax do if buffer[yy][xx][1] ~= oldBuffer[yy][xx][1] or (buffer[yy][xx][2] ~= oldBuffer[yy][xx][2] and buffer[yy][xx][1] ~= " ") or buffer[yy][xx][3] ~= oldBuffer[yy][xx][3] or buffer[yy][xx][4] ~= oldBuffer[yy][xx][4] or i == 1 then
local thisChar, thisT, thisB, xBump = chars[buffer[yy][xx][1]:byte()], buffer[yy][xx][2], buffer[yy][xx][3], (xx - xMin) * charW
if thisChar then
@@ -500,35 +502,35 @@ end
for y = 1, charH do for x = 1, charW do if thisChar[y][x] then thisFrame[y + yBump][x + xBump] = thisT end end end
end
end end
for y = yBump + 1, yBump + charH do
local skip, chars, row = 0, {}, {}
for x = 1, #thisFrame[y] do
if thisFrame[y][x] == " " then
if #chars > 0 then
row[#row + 1] = table.concat(chars)
chars = {}
end
skip = skip + 1
else
if skip > 0 then
row[#row + 1] = skip
skip = 0
end
chars[#chars + 1] = thisFrame[y][x]
end
end
if #chars > 0 then row[#row + 1] = table.concat(chars) end
thisFrame[y] = row
end
snooze()
end
if changed then
image[#image + 1] = thisFrame
else

View File

@@ -20,7 +20,7 @@ local changedPage = UI.Page {
grid = UI.Grid {
ey = -6,
columns = {
{ heading = 'Qty', key = 'count', width = 5 },
{ heading = 'Qty', key = 'count', width = 6 },
{ heading = 'Change', key = 'change', width = 6 },
{ heading = 'Rate', key = 'rate', width = 6 },
{ heading = 'Name', key = 'displayName' },
@@ -64,6 +64,7 @@ function changedPage.grid:getDisplayValues(row)
row.change = ind .. Util.toBytes(row.change)
row.count = Util.toBytes(row.count)
row.rate = Util.toBytes(row.rate)
return row
end