builder upgrade

This commit is contained in:
kepler155c@gmail.com 2017-04-01 19:21:49 -04:00
parent 74e93068fb
commit 72bd16502b
14 changed files with 977 additions and 160 deletions

View File

@ -68,9 +68,6 @@ end
function page:enable()
self:setFocus(self.prompt)
UI.Page.enable(self)
if not device then
self.menuBar.Device:disable()
end
end
local function autocomplete(env, oLine, x)
@ -131,6 +128,13 @@ function page:eventHandler(event)
self.prompt:updateCursor()
elseif event.type == 'device' then
if not _G.device then
sandboxEnv.device = { }
for _,side in pairs(peripheral.getNames()) do
local key = string.format('%s:%s', peripheral.getType(side), side)
sandboxEnv.device[ key ] = peripheral.wrap(side)
end
end
self:setPrompt('device', true)
self:executeStatement('device')

View File

@ -86,7 +86,7 @@ local systemPage = UI.Page {
grid = UI.ScrollingGrid {
y = 4,
values = {
{ name = 'CC version', value = os.version() },
{ name = 'CC version', value = os.getVersion() },
{ name = 'Lua version', value = _VERSION },
{ name = 'MC version', value = _MC_VERSION or 'unknown' },
{ name = 'Disk free', value = Util.toBytes(fs.getFreeSpace('/')) },

View File

@ -11,11 +11,15 @@ local UI = require('ui')
local Schematic = require('schematic')
local Profile = require('profile')
local TableDB = require('tableDB')
local ChestProvider = require('chestProvider')
local MEProvider = require('meProvider')
local Blocks = require('blocks')
local Point = require('point')
local ChestProvider = require('chestProvider')
if os.getVersion() == 1.8 then
ChestProvider = require('chestProvider18')
end
Logger.filter('modem_send', 'event', 'ui')
if device.wireless_modem then
@ -38,24 +42,10 @@ local Builder = {
fuelItem = { id = 'minecraft:coal', dmg = 0 },
resourceSlots = 15,
facing = 'south',
confirmFacing = false,
}
-- these wrenches work relative to the turtle
local GoodWrenches = {
[ 'appliedEnergistics2:item.ToolCertusQuartzWrench' ] = true,
[ 'appliedEnergistics2:item.ToolNetherQuartzWrench' ] = true,
[ 'EnderIO:itemYetaWrench' ] = true,
}
--[[
-- these wrenches work but take more hits to turn a piston
local BadButUsableWrenches = {
[ 'ThermalExpansion:wrench' ] = true,
[ 'MineFactoryReloaded:hammer' ] = true,
[ 'ImmersiveEngineering:tool' ] = true,
}
--]]
local pistonFacings
--[[-- SubDB --]]--
subDB = TableDB({
@ -359,7 +349,7 @@ function Builder:getBlockCounts()
local blocks = { }
-- add a couple essential items to the supply list to allow replacements
local wrench = subDB:getSubstitutedItem('ThermalExpansion:wrench', 0)
local wrench = subDB:getSubstitutedItem('SubstituteAWrench', 0)
wrench.qty = 0
wrench.need = 1
blocks[wrench.id .. ':' .. wrench.dmg] = wrench
@ -461,7 +451,7 @@ function Builder:getSupplyList(blockIndex)
index = 15,
}
local wrench = subDB:getSubstitutedItem('ThermalExpansion:wrench', 0)
local wrench = subDB:getSubstitutedItem('SubstituteAWrench', 0)
slots[16] = {
id = wrench.id,
dmg = wrench.dmg,
@ -612,9 +602,7 @@ function Builder:getSupplies()
if s.need > 0 then
local item = self.itemProvider:getItemInfo(s.id, s.dmg)
if item then
if item.name then
s.name = item.name
end
s.name = item.name
local qty = math.min(s.need - s.qty, item.qty)
@ -629,6 +617,8 @@ function Builder:getSupplies()
self.itemProvider:provide(item, qty, s.index)
s.qty = turtle.getItemCount(s.index)
end
else
s.name = blocks.blockDB:getName(s.id, s.dmg)
end
end
if s.qty < s.need then
@ -855,26 +845,83 @@ end
function Builder:getWrenchSlot()
local wrench = subDB:getSubstitutedItem('ThermalExpansion:wrench', 0)
local wrench = subDB:getSubstitutedItem('SubstituteAWrench', 0)
return Builder:selectItem(wrench.id, wrench.dmg)
end
function Builder:wrenchBlock(side, count)
function Builder:getTurtleFacing()
if os.getVersion() == 1.8 then
local directions = { -- reversed directions
[5] = 'west',
[3] = 'north',
[4] = 'east',
[2] = 'south',
}
if self:selectItem('minecraft:piston', 0) then
turtle.placeUp()
local _, bi = turtle.inspectUp()
turtle.digUp()
return directions[bi.metadata]
end
return
end
return Builder.facing
end
function Builder:wrenchBlock(side, facing)
local s = Builder:getWrenchSlot()
if not s then
b.needResupply = true
return
return false
end
turtle.select(s.index)
for i = 1,count do
local key = turtle.point.heading .. '-' .. facing
local count = pistonFacings[side][key]
if count then
turtle.select(s.index)
for i = 1,count do
turtle.getAction(side).place()
end
return true
end
local directions = {
[5] = 'east',
[3] = 'south',
[4] = 'west',
[2] = 'north',
[0] = 'down',
[1] = 'up',
}
if turtle.getHeadingInfo(facing).heading < 4 then
local offsetDirection = (turtle.getHeadingInfo(Builder.facing).heading +
turtle.getHeadingInfo(facing).heading) % 4
facing = turtle.getHeadingInfo(offsetDirection).direction
end
count = 0
print('determining wrench count')
for i = 1, 6 do
local _, bi = turtle.getAction(side).inspect()
local pistonFacing = directions[bi.metadata]
if facing == pistonFacing then
pistonFacings[side][key] = count
return true
end
count = count + 1
turtle.getAction(side).place()
end
return true
return false
end
-- place piston, wrench piston to face downward, extend, remove piston
@ -890,15 +937,10 @@ function Builder:placePiston(b)
end
if not turtle.place(ps.index) then
return false
return
end
local wrenchCount = 5
if GoodWrenches[ws.id] then
wrenchCount = 2
end
local success = self:wrenchBlock('forward', wrenchCount) --wrench piston to point downwards
local success = self:wrenchBlock('forward', 'down') --wrench piston to point downwards
rs.setOutput('front', true)
os.sleep(.25)
@ -907,7 +949,7 @@ function Builder:placePiston(b)
turtle.select(ps.index)
turtle.dig()
return true
return success
end
function Builder:goto(x, z, y, heading)
@ -1008,6 +1050,10 @@ function Builder:placeDirectionalBlock(b, slot, travelPlane)
local isSouth = (turtle.getHeadingInfo(Builder.facing).heading +
turtle.getHeadingInfo(stairUpDirections[d]).heading) % 4 == 1
if os.getVersion() == 1.8 then
isSouth = false -- no stair bug in this version
end
if isSouth then
-- for some reason, the south facing stair doesn't place correctly
@ -1058,6 +1104,7 @@ function Builder:placeDirectionalBlock(b, slot, travelPlane)
[ 'piston-west' ] = 'west',
[ 'piston-east' ] = 'east',
[ 'piston-down' ] = 'down',
[ 'piston-up' ] = 'up',
}
if pistonDirections[d] then
@ -1071,55 +1118,23 @@ function Builder:placeDirectionalBlock(b, slot, travelPlane)
return false
end
if GoodWrenches[ws.id] then
-- piston turns relative to turtle position :)
local rotatedPistonDirections = {
[ 'piston-east' ] = 'south',
[ 'piston-south' ] = 'west',
[ 'piston-west' ] = 'north',
[ 'piston-north' ] = 'east',
[ 'piston-down' ] = 'down',
}
-- piston turns relative to turtle position :)
local rotatedPistonDirections = {
[ 'piston-east' ] = 0,
[ 'piston-south' ] = 1,
[ 'piston-west' ] = 2,
[ 'piston-north' ] = 3,
}
local wrenchCount
self:gotoEx(b.x, b.z, b.y, nil, travelPlane)
if d == 'piston-down' then
self:gotoEx(b.x -1, b.z, b.y, 0, travelPlane)
wrenchCount = 2
else
local hi = turtle.getHeadingInfo(rotatedPistonDirections[d])
self:gotoEx(b.x + hi.xd, b.z + hi.zd, b.y, (hi.heading + 2) % 4, travelPlane)
wrenchCount = 1
end
local heading = rotatedPistonDirections[d]
if heading and turtle.point.heading % 2 ~= heading % 2 then
turtle.setHeading(heading)
end
if self:place(slot) then
self:wrenchBlock('forward', wrenchCount)
turtle.up()
b.placed = self:placePiston(b)
end
else -- cresent wrench
-- piston turns relative to the world :(
local wrenchCounts = {
[ 1 ] = 4, -- east
[ 2 ] = 2, -- south
[ 3 ] = 3, -- west
[ 4 ] = 1, -- north
}
self:goto(b.x, b.z, b.y, nil, travelPlane)
local wrenchCount = 5
if d ~= 'piston-down' then
local offsetDirection = (turtle.getHeadingInfo(Builder.facing).heading +
turtle.getHeadingInfo(pistonDirections[d]).heading) % 4
wrenchCount = wrenchCounts[offsetDirection + 1]
end
if self:placeDown(slot) then
b.placed = self:wrenchBlock('down', wrenchCount)
end
if self:placeDown(slot) then
b.placed = self:wrenchBlock('down', pistonDirections[d])
end
end
@ -1254,6 +1269,13 @@ function Builder:build()
else
travelPlane = self:findTravelPlane(self.index)
turtle.status = 'building'
if not self.confirmFacing then
local facing = self:getTurtleFacing()
if facing then
self.confirmFacing = true
self.facing = facing
end
end
end
UI:setPage('blank')
@ -1366,6 +1388,11 @@ function blankPage:draw()
self:setCursorPos(1, 1)
end
function blankPage:enable()
self:sync()
UI.Page.enable(self)
end
--[[-- selectSubstitutionPage --]]--
selectSubstitutionPage = UI.Page({
titleBar = UI.TitleBar({
@ -1524,6 +1551,7 @@ function substitutionPage:eventHandler(event)
elseif event.type == 'accept' or event.type == 'air' or event.type == 'revert' then
self.statusBar:setStatus('Saving changes...')
self.statusBar:draw()
self:sync()
if event.type == 'air' then
self:applySubstitute('minecraft:air', 0)
@ -1674,8 +1702,8 @@ listingPage = UI.Page({
grid = UI.ScrollingGrid({
columns = {
{ heading = 'Name', key = 'name', width = UI.term.width - 14 },
{ heading = 'Need', key = 'fNeed', width = 5 },
{ heading = 'Have', key = 'fQty', width = 5 },
{ heading = 'Need', key = 'need', width = 5 },
{ heading = 'Have', key = 'qty', width = 5 },
},
sortColumn = 'name',
y = 3,
@ -1743,6 +1771,13 @@ function listingPage:eventHandler(event)
return UI.Page.eventHandler(self, event)
end
function listingPage.grid:getDisplayValues(row)
row = Util.shallowCopy(row)
row.need = Util.toBytes(row.need)
row.qty = Util.toBytes(row.qty)
return row
end
function listingPage.grid:getRowTextColor(row, selected)
if row.is_craftable then
return colors.yellow
@ -1759,13 +1794,15 @@ function listingPage:refresh()
for _,b in pairs(supplyList) do
if b.need > 0 then
local item = Builder.itemProvider:getItemInfo(b.id, b.dmg)
if item then
local block = blocks.blockDB:lookup(b.id, b.dmg)
if not block then
blocks.blockDB:add(b.id, b.dmg, item.name)
blocks.blockDB:add(b.id, b.dmg, item.name, b.id)
elseif not blocks.name and item.name then
blocks.blockDB:add(b.id, b.dmg, item.name)
end
b.name = item.name
b.qty = item.qty
b.is_craftable = item.is_craftable
elseif not b.name then
@ -1775,19 +1812,17 @@ function listingPage:refresh()
end
blocks.blockDB:flush()
local t = {}
for _,b in pairs(supplyList) do
local block = blocks.blockDB:lookup(b.id, b.dmg)
if block then
b.name = block.name
if self.fullList then
self.grid:setValues(supplyList)
else
local t = {}
for _,b in pairs(supplyList) do
if self.fullList or b.qty < b.need then
table.insert(t, b)
end
end
if self.fullList or b.qty < b.need then
table.insert(t, b)
end
b.fNeed = Util.toBytes(b.need)
b.fQty = Util.toBytes(b.qty)
self.grid:setValues(t)
end
self.grid:setValues(t)
self.grid:setIndex(1)
end
@ -1882,13 +1917,19 @@ function startPage:eventHandler(event)
if event.type == 'startLevel' then
local dialog = UI.Dialog({
text = UI.Text({ x = 5, y = 3, value = '0 - ' .. schematic.height }),
textEntry = UI.TextEntry({ x = 15, y = 3, '0 - 11' })
title = 'Enter Starting Level',
height = 7,
form = UI.Form {
y = 3, x = 2, height = 4,
text = UI.Text({ x = 5, y = 1, textColor = colors.gray, value = '0 - ' .. schematic.height }),
textEntry = UI.TextEntry({ x = 15, y = 1, '0 - 11', width = 7 }),
},
statusBar = UI.StatusBar(),
})
dialog.eventHandler = function(self, event)
if event.type == 'accept' then
local l = tonumber(self.textEntry.value)
if event.type == 'form_complete' then
local l = tonumber(self.form.textEntry.value)
if l and l < schematic.height and l >= 0 then
for k,v in pairs(schematic.blocks) do
if v.y >= l then
@ -1901,25 +1942,32 @@ function startPage:eventHandler(event)
else
self.statusBar:timedStatus('Invalid Level', 3)
end
return true
elseif event.type == 'form_cancel' or event.type == 'cancel' then
UI:setPreviousPage()
else
return UI.Dialog.eventHandler(self, event)
end
return UI.Dialog.eventHandler(self, event)
return true
end
dialog.titleBar.title = 'Enter Starting Level'
dialog:setFocus(dialog.textEntry)
dialog:setFocus(dialog.form.textEntry)
UI:setPage(dialog)
elseif event.type == 'startBlock' then
local dialog = UI.Dialog({
text = UI.Text({ x = 5, y = 3, value = '1 - ' .. #schematic.blocks }),
textEntry = UI.TextEntry({ x = 15, y = 3, value = tostring(Builder.index) })
})
local dialog = UI.Dialog {
title = 'Enter Block Number',
height = 7,
form = UI.Form {
y = 3, x = 2, height = 4,
text = UI.Text { x = 5, y = 1, value = '1 - ' .. #schematic.blocks, textColor = colors.gray },
textEntry = UI.TextEntry { x = 15, y = 1, value = tostring(Builder.index), width = 7 }
},
statusBar = UI.StatusBar(),
}
dialog.eventHandler = function(self, event)
if event.type == 'accept' then
local bn = tonumber(self.textEntry.value)
if event.type == 'form_complete' then
local bn = tonumber(self.form.textEntry.value)
if bn and bn < #schematic.blocks and bn >= 0 then
Builder.index = bn
Builder:saveProgress(Builder.index)
@ -1927,14 +1975,15 @@ function startPage:eventHandler(event)
else
self.statusBar:timedStatus('Invalid Block', 3)
end
return true
elseif event.type == 'form_cancel' or event.type == 'cancel' then
UI:setPreviousPage()
else
return UI.Dialog.eventHandler(self, event)
end
return UI.Dialog.eventHandler(self, event)
return true
end
dialog.titleBar.title = 'Enter Block Number'
dialog:setFocus(dialog.textEntry)
dialog:setFocus(dialog.form.textEntry)
UI:setPage(dialog)
elseif event.type == 'assignBlocks' then
@ -1991,6 +2040,12 @@ function startPage:eventHandler(event)
else
print('Starting build')
end
-- reset piston cache in case wrench was substituted
pistonFacings = {
down = { },
forward = { },
}
Builder:build()
Profile.display()

603
apps/refinedManager.lua Normal file
View File

@ -0,0 +1,603 @@
local injector = requireInjector or load(http.get('http://pastebin.com/raw/c0TWsScv').readAll())()
require = injector(getfenv(1))
local Event = require('event')
local UI = require('ui')
local Peripheral = require('peripheral')
local controller = Peripheral.getByType('refinedstorage:controller')
if not controller then
error('Refined storage controller not found')
end
multishell.setTitle(multishell.getCurrent(), 'Storage Manager')
-- Strip off color prefix
local function safeString(text)
local val = text:byte(1)
if val < 32 or val > 128 then
local newText = {}
for i = 4, #text do
local val = text:byte(i)
newText[i - 3] = (val > 31 and val < 127) and val or 63
end
return string.char(unpack(newText))
end
return text
end
function listItems()
local items = { }
local list
pcall(function()
list = controller.listAvailableItems()
end)
if list then
for k,v in pairs(list) do
local item = controller.findItem(v)
if item then
Util.merge(item, item.getMetadata())
item.displayName = safeString(item.displayName)
if item.maxDamage and item.maxDamage > 0 and item.damage > 0 then
item.displayName = item.displayName .. ' (damaged)'
end
item.lname = item.displayName:lower()
table.insert(items, item)
end
end
end
return items
end
function getItem(items, inItem, ignoreDamage)
for _,item in pairs(items) do
if item.name == inItem.name then
if ignoreDamage and ignoreDamage == 'yes' then
return item
elseif item.damage == inItem.damage and item.nbtHash == inItem.nbtHash then
return item
end
end
end
end
local function uniqueKey(item)
local key = item.name .. ':' .. item.damage
if item.nbtHash then
key = key .. ':' .. item.nbtHash
end
return key
end
function mergeResources(t)
local resources = Util.readTable('resource.limits')
resources = resources or { }
for _,v in pairs(resources) do
local item = getItem(t, v)
if item then
item.limit = tonumber(v.limit)
item.low = tonumber(v.low)
item.auto = v.auto
item.ignoreDamage = v.ignoreDamage
else
v.count = 0
v.limit = tonumber(v.limit)
v.low = tonumber(v.low)
v.auto = v.auto
v.ignoreDamage = v.ignoreDamage
table.insert(t, v)
end
end
end
function filterItems(t, filter)
local r = {}
if filter then
filter = filter:lower()
for k,v in pairs(t) do
if string.find(v.lname, filter) then
table.insert(r, v)
end
end
else
return t
end
return r
end
function getJobList()
local list = { }
for _,task in pairs(controller.getCraftingTasks()) do
table.insert(list, task.getPattern().outputs[1])
end
return list
end
function craftItems(itemList, allItems)
for _,item in pairs(itemList) do
local alreadyCrafting = false
local jobList = getJobList()
for _,v in pairs(jobList) do
if v.name == item.name and v.damage == item.damage and v.nbtHash == item.nbtHash then
alreadyCrafting = true
end
end
local cItem = getItem(allItems, item)
if alreadyCrafting then
item.status = '(crafting)'
elseif not cItem then
item.status = '(no recipe)'
else
local count = item.count
while count >= 1 do -- try to request smaller quantities until successful
local s, m = pcall(function()
item.status = '(no recipe)'
if not cItem.craft(count) then
item.status = '(missing ingredients)'
error('failed')
end
item.status = '(crafting)'
end)
if s then
break -- successfully requested crafting
end
count = math.floor(count / 2)
end
end
end
end
function getAutocraftItems(items)
local t = Util.readTable('resource.limits') or { }
local itemList = { }
for _,res in pairs(t) do
if res.auto and res.auto == 'yes' then
res.count = 4 -- this could be higher to increase autocrafting speed
table.insert(itemList, res)
end
end
return itemList
end
local function getItemWithQty(items, res, ignoreDamage)
local item = getItem(items, res, ignoreDamage)
if item then
if ignoreDamage and ignoreDamage == 'yes' then
local count = 0
for _,v in pairs(items) do
if item.name == v.name and item.nbtHash == v.nbtHash then
if item.maxDamage > 0 or item.damage == v.damage then
count = count + v.count
end
end
end
item.count = count
end
end
return item
end
function watchResources(items)
local itemList = { }
local t = Util.readTable('resource.limits') or { }
for k, res in pairs(t) do
local item = getItemWithQty(items, res, res.ignoreDamage)
res.limit = tonumber(res.limit)
res.low = tonumber(res.low)
if not item then
item = {
damage = res.damage,
nbtHash = res.nbtHash,
name = res.name,
displayName = res.displayName,
count = 0
}
end
if res.low and item.count < res.low then
if res.ignoreDamage and res.ignoreDamage == 'yes' then
item.damage = 0
end
table.insert(itemList, {
damage = item.damage,
nbtHash = item.nbtHash,
count = res.low - item.count,
name = item.name,
displayName = item.displayName,
status = ''
})
end
end
return itemList
end
itemPage = UI.Page {
backgroundColor = colors.lightGray,
titleBar = UI.TitleBar {
title = 'Limit Resource',
previousPage = true,
event = 'form_cancel',
backgroundColor = colors.green
},
displayName = UI.Window {
x = 5, y = 3, width = UI.term.width - 10, height = 3,
},
form = UI.Form {
x = 4, y = 6, height = 8, rex = -4,
[1] = UI.TextEntry {
width = 7,
backgroundColor = colors.gray,
backgroundFocusColor = colors.gray,
formLabel = 'Min', formKey = 'low', help = 'Craft if below min'
},
[2] = UI.Chooser {
width = 7,
formLabel = 'Autocraft', formKey = 'auto',
nochoice = 'No',
choices = {
{ name = 'Yes', value = 'yes' },
{ name = 'No', value = 'no' },
},
help = 'Craft until out of ingredients'
},
[3] = UI.Chooser {
width = 7,
formLabel = 'Ignore Dmg', formKey = 'ignoreDamage',
nochoice = 'No',
choices = {
{ name = 'Yes', value = 'yes' },
{ name = 'No', value = 'no' },
},
help = 'Ignore damage of item'
},
},
statusBar = UI.StatusBar { }
}
function itemPage.displayName:draw()
local item = self.parent.item
local str = string.format('Name: %s\nDamage: %d', item.displayName, item.damage)
if item.nbtHash then
str = str .. string.format('\nNBT: %s\n', item.nbtHash)
end
debug(str)
self:setCursorPos(1, 1)
self:print(str)
end
function itemPage:enable(item)
self.item = item
self.form:setValues(item)
self.titleBar.title = item.name
self.displayName.value = item.displayName
UI.Page.enable(self)
self:focusFirst()
end
function itemPage:eventHandler(event)
if event.type == 'form_cancel' then
UI:setPreviousPage()
elseif event.type == 'focus_change' then
self.statusBar:setStatus(event.focused.help)
self.statusBar:draw()
elseif event.type == 'form_complete' then
local values = self.form.values
local t = Util.readTable('resource.limits') or { }
for k,v in pairs(t) do
if v.name == values.name and v.damage == values.damage then
t[k] = nil
break
end
end
local keys = { 'name', 'displayName', 'auto', 'low', 'damage', 'maxDamage', 'nbtHash', 'limit', 'ignoreDamage' }
local filtered = { }
for _,key in pairs(keys) do
filtered[key] = values[key]
end
if filtered.ignoreDamage and filtered.ignoreDamage == 'yes' then
filtered.damage = 0
end
t[uniqueKey(filtered)] = filtered
--table.insert(t, filtered)
Util.writeTable('resource.limits', t)
UI:setPreviousPage()
else
return UI.Page.eventHandler(self, event)
end
return true
end
listingPage = UI.Page {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Forget', event = 'forget' },
},
},
grid = UI.Grid {
y = 2, height = UI.term.height - 2,
columns = {
{ heading = 'Name', key = 'displayName', width = UI.term.width - 14 },
{ heading = 'Qty', key = 'count', width = 5 },
{ heading = 'Min', key = 'low', width = 4 },
},
sortColumn = 'lname',
},
statusBar = UI.StatusBar {
backgroundColor = colors.gray,
width = UI.term.width,
filterText = UI.Text {
x = 2, width = 6,
value = 'Filter',
},
filter = UI.TextEntry {
x = 9, rex = -12,
limit = 50,
},
refresh = UI.Button {
rx = -9, width = 8,
text = 'Refresh',
event = 'refresh',
},
},
accelerators = {
r = 'refresh',
q = 'quit',
}
}
function listingPage.grid:getRowTextColor(row, selected)
if row.is_craftable then -- not implemented
return colors.yellow
end
return UI.Grid:getRowTextColor(row, selected)
end
function listingPage.grid:getDisplayValues(row)
row = Util.shallowCopy(row)
row.count = Util.toBytes(row.count)
if row.low then
row.low = Util.toBytes(row.low)
end
if row.limit then
row.limit = Util.toBytes(row.limit)
end
return row
end
function listingPage.statusBar:draw()
return UI.Window.draw(self)
end
function listingPage.statusBar.filter:eventHandler(event)
if event.type == 'mouse_rightclick' then
self.value = ''
self:draw()
local page = UI:getCurrentPage()
page.filter = nil
page:applyFilter()
page.grid:draw()
page:setFocus(self)
end
return UI.TextEntry.eventHandler(self, event)
end
function listingPage:eventHandler(event)
if event.type == 'quit' then
Event.exitPullEvents()
elseif event.type == 'grid_select' then
local selected = event.selected
UI:setPage('item', selected)
elseif event.type == 'refresh' then
self:refresh()
self.grid:draw()
elseif event.type == 'forget' then
local item = self.grid:getSelected()
if item then
local resources = Util.readTable('resource.limits') or { }
resources[uniqueKey(item)] = nil
Util.writeTable('resource.limits', resources)
self.statusBar:timedStatus('Forgot: ' .. item.name, 3)
self:refresh()
self.grid:draw()
end
elseif event.type == 'text_change' then
self.filter = event.text
if #self.filter == 0 then
self.filter = nil
end
self:applyFilter()
self.grid:draw()
self.statusBar.filter:focus()
else
UI.Page.eventHandler(self, event)
end
return true
end
function listingPage:enable()
self:refresh()
self:setFocus(self.statusBar.filter)
UI.Page.enable(self)
end
function listingPage:refresh()
self.allItems = listItems()
mergeResources(self.allItems)
self:applyFilter()
end
function listingPage:applyFilter()
local t = filterItems(self.allItems, self.filter)
self.grid:setValues(t)
end
local nullDevice = {
setCursorPos = function(...) end,
write = function(...) end,
getSize = function() return 13, 20 end,
isColor = function() return false end,
setBackgroundColor = function(...) end,
setTextColor = function(...) end,
clear = function(...) end,
sync = function(...) end,
}
local function jobMonitor(jobList)
local mon = Peripheral.getByType('monitor')
if mon then
mon = UI.Device({
device = mon,
textScale = .5,
})
else
mon = UI.Device({
device = nullDevice
})
end
jobListGrid = UI.Grid {
parent = mon,
sortColumn = 'displayName',
columns = {
{ heading = 'Qty', key = 'count', width = 6 },
{ heading = 'Crafting', key = 'displayName', width = mon.width / 2 - 10 },
{ heading = 'Status', key = 'status', width = mon.width - 10 },
},
}
end
local function jobMonitor(jobList)
local mon = Peripheral.getByType('monitor')
local nullDevice = {
setCursorPos = function(...) end,
write = function(...) end,
getSize = function() return 13, 20 end,
isColor = function() return false end,
setBackgroundColor = function(...) end,
setTextColor = function(...) end,
clear = function(...) end,
sync = function(...) end,
blit = function(...) end,
}
if mon then
mon = UI.Device({
device = mon,
textScale = .5,
})
else
mon = UI.Device({
device = nullDevice
})
end
jobListGrid = UI.Grid {
parent = mon,
sortColumn = 'displayName',
columns = {
{ heading = 'Qty', key = 'count', width = 6 },
{ heading = 'Crafting', key = 'displayName', width = mon.width / 2 - 10 },
{ heading = 'Status', key = 'status', width = mon.width - 10 },
},
}
return jobListGrid
end
UI:setPages({
listing = listingPage,
item = itemPage,
})
UI:setPage(listingPage)
listingPage:setFocus(listingPage.statusBar.filter)
local jobListGrid = jobMonitor()
jobListGrid:draw()
jobListGrid:sync()
function craftingThread()
while true do
os.sleep(5)
pcall(function()
local items = listItems()
if controller.getNetworkEnergyStored() == 0 then
jobListGrid.parent:clear()
jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'Power failure')
jobListGrid:sync()
elseif Util.size(items) == 0 then
jobListGrid.parent:clear()
jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'No items in system')
jobListGrid:sync()
else
local itemList = watchResources(items)
jobListGrid:setValues(itemList)
jobListGrid:draw()
jobListGrid:sync()
craftItems(itemList, items)
jobListGrid:update()
jobListGrid:draw()
jobListGrid:sync()
itemList = getAutocraftItems(items) -- autocrafted items don't show on job monitor
craftItems(itemList, items)
end
end)
end
end
Event.pullEvents(craftingThread)
UI.term:reset()
jobListGrid.parent:reset()

View File

@ -24,6 +24,11 @@ local options = {
local MIN_FUEL = 7500
local LOW_FUEL = 1500
local MAX_FUEL = 100000
if not term.isColor() then
MAX_FUEL = 20000
end
local mining = {
diameter = 1,
@ -175,6 +180,7 @@ end
function refuel()
if turtle.getFuelLevel() < MIN_FUEL then
local oldStatus = turtle.status
status('refueling')
if turtle.selectSlot('minecraft:coal:0') then
@ -193,7 +199,7 @@ function refuel()
end)
end
log('Fuel: ' .. turtle.getFuelLevel())
status('boring')
status(oldStatus)
end
turtle.select(1)
@ -315,7 +321,7 @@ function mineable(action)
collectDrops(action.suck)
end
if turtle.getFuelLevel() < 99000 then
if turtle.getFuelLevel() < (MAX_FUEL - 1000) then
if block.name == 'minecraft:lava' or block.name == 'minecraft:flowing_lava' then
if turtle.selectSlot('minecraft:bucket:0') then
if action.place() then
@ -546,6 +552,7 @@ end
local function main()
repeat
while #mining.locations > 0 do
status('searching')
if not boreCommand() then
return
end

View File

@ -6,6 +6,11 @@ local Point = require('point')
local TableDB = require('tableDB')
local MEProvider = require('meProvider')
local ChestProvider = require('chestProvider')
if os.getVersion() == 1.8 then
ChestProvider = require('chestProvider18')
end
if not device.wireless_modem then
error('No wireless modem detected')
end
@ -324,9 +329,9 @@ Message.addHandler('needSupplies',
turtle.select(15)
turtle.placeDown()
os.sleep(.1) -- random computer not connected error
local p = peripheral.wrap('bottom')
local p = ChestProvider({ direction = 'up', wrapSide = 'bottom' })
for i = 1, 16 do
p.pullItem('up', i, 64)
p:insert(i, 64)
end
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true, point = pt })
@ -334,9 +339,9 @@ Message.addHandler('needSupplies',
Message.waitForMessage('thanks', 5, __BUILDER_ID)
--os.sleep(0)
p.condenseItems()
--p.condenseItems()
for i = 1, 16 do
p.pushItem('up', i, 64)
p:extract(i, 64)
end
turtle.digDown()
turtle.status = 'waiting'
@ -386,6 +391,12 @@ turtle.setPoint({ x = -1, z = -2, y = 0, heading = 0 })
turtle.saveLocation('supplies')
Builder.itemProvider = MEProvider()
if not Builder.itemProvider:isValid() then
Builder.itemProvider = ChestProvider()
if not Builder.itemProvider:isValid() then
error('A chest or ME interface must be below turtle')
end
end
turtle.run(function()
Event.pullEvents(onTheWay)

View File

@ -96,15 +96,13 @@ function blockDB:seedDB(dir)
end
lastID = strId
local sep = string.find(line[2], ':')
if not sep then
nid = tonumber(line[2])
dmg = 0
else
nid = tonumber(string.sub(line[2], 1, sep - 1))
dmg = tonumber(string.sub(line[2], sep + 1, #line[2]))
local t = { }
string.gsub(line[2], '(%d+)', function(d) table.insert(t, d) end)
nid = tonumber(t[1])
dmg = 0
if t[2] then
dmg = tonumber(t[2])
end
self:add(nid, dmg, name, strId)
end
@ -653,13 +651,13 @@ function blockTypeDB:seedDB()
})
blockTypeDB:addTemp('piston', { -- piston placement is broken in 1.7 -- need to add work around
{ 0, nil, 0, 'piston-down' },
{ 1, nil, 0 },
{ 1, nil, 0, 'piston-up' },
{ 2, nil, 0, 'piston-north' },
{ 3, nil, 0, 'piston-south' },
{ 4, nil, 0, 'piston-west' },
{ 5, nil, 0, 'piston-east' },
{ 8, nil, 0, 'piston-down' },
{ 9, nil, 0 },
{ 9, nil, 0, 'piston-up' },
{ 10, nil, 0, 'piston-north' },
{ 11, nil, 0, 'piston-south' },
{ 12, nil, 0, 'piston-west' },

View File

@ -54,7 +54,9 @@ function ChestProvider:getItemInfo(id, dmg)
item.max_size = stack.max_size
end
end
return item
if item.name then
return item
end
end
function ChestProvider:craft(id, dmg, qty)
@ -79,7 +81,13 @@ function ChestProvider:provide(item, qty, slot)
end
end
end
function ChestProvider:extract(slot, qty)
if self.p then
self.p.pushItem(self.direction, slot, qty)
end
end
function ChestProvider:insert(slot, qty)
if self.p then
local s, m = pcall(function() self.p.pullItem(self.direction, slot, qty) end)

View File

@ -0,0 +1,103 @@
local class = require('class')
local Logger = require('logger')
local ChestProvider = class()
function ChestProvider:init(args)
args = args or { }
self.stacks = {}
self.name = 'chest'
self.direction = args.direction or 'up'
self.wrapSide = args.wrapSide or 'bottom'
self.p = peripheral.wrap(self.wrapSide)
end
function ChestProvider:isValid()
return self.p and self.p.list
end
function ChestProvider:refresh()
if self.p then
--self.p.condenseItems()
self.stacks = self.p.list()
local t = { }
for _,s in pairs(self.stacks) do
s.id = s.name
s.dmg = s.damage
s.qty = s.count
local key = s.id .. ':' .. s.dmg
if t[key] and t[key].qty < 64 then
t[key].max_size = t[key].qty
else
t[key] = {
qty = s.qty
}
end
end
for _,s in ipairs(self.stacks) do
local key = s.id .. ':' .. s.dmg
if t[key].max_size then
s.max_size = t[key].qty
else
s.max_size = 64
end
end
end
return self.stacks
end
function ChestProvider:getItemInfo(id, dmg)
local item = { id = id, dmg = dmg, qty = 0, max_size = 64 }
for k,stack in pairs(self.stacks) do
if stack.id == id and stack.dmg == dmg then
local meta = self.p.getItemMeta(k)
if meta then
item.name = meta.displayName
item.qty = item.qty + meta.count
item.max_size = meta.maxCount
end
end
end
if item.name then
return item
end
end
function ChestProvider:craft(id, dmg, qty)
return false
end
function ChestProvider:craftItems(items)
end
function ChestProvider:provide(item, qty, slot)
if self.p then
self:refresh()
for key,stack in pairs(self.stacks) do
if stack.id == item.id and stack.dmg == item.dmg then
local amount = math.min(qty, stack.qty)
self.p.pushItems(self.direction, key, amount, slot)
qty = qty - amount
if qty <= 0 then
break
end
end
end
end
end
function ChestProvider:extract(slot, qty)
if self.p then
self.p.pushItems(self.direction, slot, qty)
end
end
function ChestProvider:insert(slot, qty)
if self.p then
self.p.pullItems(self.direction, slot, qty)
end
end
return ChestProvider

View File

@ -1,6 +1,21 @@
local Peripheral = { }
function Peripheral.addDevice(side)
local function getDeviceList()
if _G.device then
return _G.device
end
local deviceList = { }
for _,side in pairs(peripheral.getNames()) do
Peripheral.addDevice(deviceList, side)
end
return deviceList
end
function Peripheral.addDevice(deviceList, side)
local name = side
local ptype = peripheral.getType(side)
@ -28,33 +43,33 @@ function Peripheral.addDevice(side)
if sides[name] then
local i = 1
local uniqueName = ptype
while device[uniqueName] do
while deviceList[uniqueName] do
uniqueName = ptype .. '_' .. i
i = i + 1
end
name = uniqueName
end
device[name] = peripheral.wrap(side)
Util.merge(device[name], {
deviceList[name] = peripheral.wrap(side)
Util.merge(deviceList[name], {
name = name,
type = ptype,
side = side,
})
return device[name]
return deviceList[name]
end
function Peripheral.getBySide(side)
return Util.find(device, 'side', side)
return Util.find(getDeviceList(), 'side', side)
end
function Peripheral.getByType(typeName)
return Util.find(device, 'type', typeName)
return Util.find(getDeviceList(), 'type', typeName)
end
function Peripheral.getByMethod(method)
for _,p in pairs(device) do
for _,p in pairs(getDeviceList()) do
if p[method] then
return p
end

View File

@ -438,6 +438,7 @@ end
function Manager:pullEvents(...)
Event.pullEvents(...)
self.term:reset()
end
function Manager:exitPullEvents()
@ -1075,7 +1076,7 @@ function UI.TransitionSlideLeft:update(device)
self.canvas:blit(device, {
x = self.x,
y = self.y,
ex = self.ex - x + self.x + 1,
ex = self.ex - x + self.x,
ey = self.ey },
{ x = x, y = self.y })
end
@ -1108,13 +1109,13 @@ function UI.TransitionSlideRight:update(device)
self.lastScreen:blit(device, {
x = self.x,
y = self.y,
ex = self.ex - x + self.x + 1,
ex = self.ex - x + self.x,
ey = self.ey },
{ x = x, y = self.y })
self.canvas:blit(device, {
x = self.ex - x + self.x,
y = self.y,
ex = self.ex + 1,
ex = self.ex,
ey = self.ey },
{ x = self.x, y = self.y })
end
@ -1431,8 +1432,6 @@ end
UI.Grid = class(UI.Window)
UI.Grid.defaults = {
UIElement = 'Grid',
x = 1,
y = 1,
index = 1,
inverseSort = false,
disableHeader = false,
@ -2571,7 +2570,7 @@ UI.StatusBar.defaults = {
function UI.StatusBar:init(args)
local defaults = UI:getDefaults(UI.StatusBar, args)
UI.GridLayout.init(self, defaults)
self:setStatus(self.status)
self:setStatus(self.status, true)
end
function UI.StatusBar:setParent()
@ -2583,12 +2582,15 @@ function UI.StatusBar:setParent()
end
end
function UI.StatusBar:setStatus(status)
function UI.StatusBar:setStatus(status, noDraw)
if type(status) == 'string' then
self.values[1] = { status = status }
else
self.values[1] = status
end
if not noDraw then
self:draw()
end
end
function UI.StatusBar:setValue(name, value)
@ -2796,7 +2798,8 @@ function UI.TextEntry:updateScroll()
elseif self.pos < self.scroll then
self.scroll = self.pos
end
-- debug('p:%d s:%d w:%d l:%d', self.pos, self.scroll, self.width, self.limit)
--debug('p:%d s:%d w:%d l:%d', self.pos, self.scroll, self.width, self.limit)
end
function UI.TextEntry:draw()
@ -2910,7 +2913,7 @@ function UI.TextEntry:eventHandler(event)
return true
elseif event.type == 'mouse_click' then
if self.focused then
if self.focused and event.x > 1 then
self.pos = event.x + self.scroll - 2
self:updateCursor()
return true
@ -3166,7 +3169,7 @@ function UI.Dialog:init(args)
titleBar = UI.TitleBar({ previousPage = true, title = defaults.title }),
})
UI.setProperties(defaults, args)
--UI.setProperties(defaults, args)
UI.Page.init(self, defaults)
end
@ -3266,8 +3269,8 @@ function UI.NftImage:setImage(image)
end
UI:loadTheme('config/ui.theme')
if _HOST and string.find(_HOST, 'CCEmuRedux') then
UI:loadTheme('config/ccemuredux.theme')
if os.getVersion() >= 1.79 then
UI:loadTheme('config/ext.theme')
end
UI:setDefaultDevice(UI.Device({ device = term.current() }))

View File

@ -4,5 +4,5 @@ require = requireInjector(getfenv(1))
local Peripheral = require('peripheral')
for _,side in pairs(peripheral.getNames()) do
Peripheral.addDevice(side)
Peripheral.addDevice(device, side)
end

View File

@ -90,6 +90,16 @@ function os.isPocket()
return not not pocket
end
function os.getVersion()
if _CC_VERSION then
return tonumber(_CC_VERSION)
end
if _HOST then
return tonumber(_HOST:gmatch('[%d]+%.?[%d][%d]', '%1')())
end
return 1.7
end
function os.registerApp(entry)
local apps = { }
Config.load('apps', apps)

View File

@ -14,7 +14,7 @@ end
Event.addHandler('peripheral', function(event, side)
if side then
local dev = Peripheral.addDevice(side)
local dev = Peripheral.addDevice(device, side)
if dev then
term.setTextColor(attachColor)
Util.print('[%s] %s attached', dev.side, dev.name)