This commit is contained in:
kepler155c
2017-09-18 14:46:21 -04:00
parent b4d3160cd8
commit 4116e046d1
14 changed files with 2491 additions and 2211 deletions

View File

@@ -42,7 +42,7 @@ local blockDB = TableDB()
function blockDB:load()
local blocks = JSON.decodeFromFile('usr/etc/blocks.json'))
local blocks = JSON.decodeFromFile('usr/etc/blocks.json')
if not blocks then
error('Unable to read blocks.json')

View File

@@ -3,6 +3,20 @@ local TableDB = require('tableDB')
local itemDB = TableDB({ fileName = 'usr/config/items.db' })
local function splitKey(key, item)
item = item or { }
local t = Util.split(key, '(.-):')
if #t[#t] > 8 then
item.nbtHash = table.remove(t)
end
item.damage = tonumber(table.remove(t))
item.name = table.concat(t, ':')
return item
end
function itemDB:get(key)
local item = TableDB.get(self, key)
@@ -34,6 +48,54 @@ function itemDB:makeKey(item)
return { item.name, item.damage, item.nbtHash }
end
-- Accepts: "minecraft:stick:0" or { name = 'minecraft:stick', damage = 0 }
function itemDB:getName(item)
if type(item) == 'string' then
item = splitKey(item)
end
local detail = self:get(self:makeKey(item))
if detail then
return detail.displayName
end
return item.name .. ':' .. item.damage
end
function itemDB:load()
TableDB.load(self)
for key,item in pairs(self.data) do
splitKey(key, item)
item.maxDamage = item.maxDamage or 0
item.maxCount = item.maxCount or 64
end
end
function itemDB:flush()
if self.dirty then
local t = { }
for k,v in pairs(self.data) do
v = Util.shallowCopy(v)
v.name = nil
v.damage = nil
v.nbtHash = nil
if v.maxDamage == 0 then
v.maxDamage = nil
end
if v.maxCount == 64 then
v.maxCount = nil
end
t[k] = v
end
Util.writeTable(self.fileName, t)
self.dirty = false
end
end
itemDB:load()
return itemDB

View File

@@ -27,7 +27,7 @@ function RefinedAdapter:init(args)
Util.merge(self, controller)
end
end
function RefinedAdapter:isValid()
return not not self.listAvailableItems
end

View File

@@ -7,17 +7,15 @@ function TableDB:init(args)
fileName = '',
dirty = false,
data = { },
tabledef = { },
}
Util.merge(defaults, args)
Util.merge(self, defaults)
end
function TableDB:load()
local table = Util.readTable(self.fileName)
if table then
self.data = table.data
self.tabledef = table.tabledef
local t = Util.readTable(self.fileName)
if t then
self.data = t.data or t
end
end
@@ -43,10 +41,7 @@ end
function TableDB:flush()
if self.dirty then
Util.writeTable(self.fileName, {
-- tabledef = self.tabledef,
data = self.data,
})
Util.writeTable(self.fileName, self.data)
self.dirty = false
end
end

View File

@@ -3,11 +3,11 @@ local Util = require('util')
local Craft = { }
local function clearGrid(chestAdapter)
local function clearGrid(inventoryAdapter)
for i = 1, 16 do
local count = turtle.getItemCount(i)
if count > 0 then
chestAdapter:insert(i, count)
inventoryAdapter:insert(i, count)
if turtle.getItemCount(i) ~= 0 then
return false
end
@@ -19,7 +19,7 @@ end
local function splitKey(key)
local t = Util.split(key, '(.-):')
local item = { }
if #t[#t] > 2 then
if #t[#t] > 8 then
item.nbtHash = table.remove(t)
end
item.damage = tonumber(table.remove(t))
@@ -39,13 +39,13 @@ local function getItemCount(items, key)
return 0
end
local function turtleCraft(recipe, qty, chestAdapter)
local function turtleCraft(recipe, qty, inventoryAdapter)
clearGrid(chestAdapter)
clearGrid(inventoryAdapter)
for k,v in pairs(recipe.ingredients) do
local item = splitKey(v)
chestAdapter:provide(item, qty, k)
inventoryAdapter:provide(item, qty, k)
if turtle.getItemCount(k) == 0 then -- ~= qty then
-- FIX: ingredients cannot be stacked
return false
@@ -55,9 +55,9 @@ local function turtleCraft(recipe, qty, chestAdapter)
return turtle.craft()
end
function Craft.craftRecipe(recipe, count, chestAdapter)
function Craft.craftRecipe(recipe, count, inventoryAdapter)
local items = chestAdapter:listItems()
local items = inventoryAdapter:listItems()
local function sumItems(items)
-- produces { ['minecraft:planks:0'] = 8 }
@@ -78,10 +78,10 @@ function Craft.craftRecipe(recipe, count, chestAdapter)
if itemCount < icount * count then
local irecipe = Craft.recipes[key]
if irecipe then
Util.print('Crafting %d %s', icount * count - itemCount, key)
--Util.print('Crafting %d %s', icount * count - itemCount, key)
if not Craft.craftRecipe(irecipe,
icount * count - itemCount,
chestAdapter) then
inventoryAdapter) then
turtle.select(1)
return
end
@@ -89,7 +89,7 @@ Util.print('Crafting %d %s', icount * count - itemCount, key)
end
end
repeat
if not turtleCraft(recipe, math.min(count, maxCount), chestAdapter) then
if not turtleCraft(recipe, math.min(count, maxCount), inventoryAdapter) then
turtle.select(1)
return false
end
@@ -101,7 +101,7 @@ Util.print('Crafting %d %s', icount * count - itemCount, key)
end
-- given a certain quantity, return how many of those can be crafted
function Craft.getCraftableAmount(recipe, count, items)
function Craft.getCraftableAmount(recipe, count, items, missing)
local function sumItems(recipe, items, summedItems, count)
@@ -116,6 +116,9 @@ function Craft.getCraftableAmount(recipe, count, items)
summedItem = summedItem + sumItems(irecipe, items, summedItems, 1)
end
if summedItem <= 0 then
if missing then
missing.name = item
end
return canCraft
end
summedItems[item] = summedItem - 1
@@ -126,7 +129,7 @@ function Craft.getCraftableAmount(recipe, count, items)
return canCraft
end
return sumItems(recipe, items, { }, math.ceil(count / recipe.count))
return sumItems(recipe, items, { }, math.ceil(count / recipe.count), missing)
end
function Craft.canCraft(item, count, items)

View File

@@ -2,8 +2,8 @@ local Point = require('point')
local Util = require('util')
local checkedNodes = { }
local nodes = { }
local box = { }
local nodes = { }
local box = { }
local oldCallback
local function toKey(pt)
@@ -149,7 +149,7 @@ return function(startPt, endPt, firstPt, verbose)
print(string.format('%d nodes remaining', Util.size(nodes)))
end
if Util.size(nodes) == 0 then
if not next(nodes) then
break
end

View File

@@ -140,18 +140,22 @@ function page:enable(turtle)
end
function page:runFunction(script, nowrap)
if not socket then
socket = Socket.connect(self.turtle.id, 161)
for i = 1, 2 do
if not socket then
self.notification:error('Unable to connect')
return
socket = Socket.connect(self.turtle.id, 161)
end
end
if not nowrap then
script = 'turtle.run(' .. script .. ')'
if socket then
if not nowrap then
script = 'turtle.run(' .. script .. ')'
end
if socket:write({ type = 'script', args = script }) then
return true
end
end
socket = nil
end
socket:write({ type = 'script', args = script })
self.notification:error('Unable to connect')
end
function page:runScript(scriptName)
@@ -270,6 +274,7 @@ end
function page.tabs.turtles:eventHandler(event)
if event.type == 'grid_select' then
page.turtle = event.selected
multishell.setTitle(multishell.getCurrent(), page.turtle.label)
if socket then
socket:close()
socket = nil

View File

@@ -1447,7 +1447,7 @@ substitutionPage = UI.Page {
{ heading = 'Name', key = 'display_name', width = UI.term.width-9 },
{ heading = 'Qty', key = 'fQty', width = 5 },
},
sortColumn = 'name',
sortColumn = 'display_name',
height = UI.term.height-7,
y = 7,
},

View File

@@ -31,8 +31,8 @@ if not controller:isValid() then
controller = nil
end
local chestAdapter = ChestAdapter({ direction = 'west', wrapSide = 'back' })
local turtleChestAdapter = ChestAdapter({ direction = 'up', wrapSide = 'bottom' })
local chestAdapter = ChestAdapter({ direction = 'north', wrapSide = 'colossalchests:colossalChest_0' })
local turtleChestAdapter = ChestAdapter({ direction = 'down', wrapSide = 'top' })
local RESOURCE_FILE = 'usr/config/resources.db'
local RECIPES_FILE = 'usr/etc/recipes.db'
@@ -40,27 +40,10 @@ local RECIPES_FILE = 'usr/etc/recipes.db'
local jobListGrid
local craftingPaused = false
local recipes = Util.readTable(RECIPES_FILE) or { }
local resources = Util.readTable(RESOURCE_FILE) or { }
local resources
Craft.setRecipes(recipes)
for _,r in pairs(resources) do
r.maxDamage = nil
r.displayName = nil
r.count = nil
r.lname = nil
r.has_recipe = nil
if not r.ignoreDamage then
r.ignoreDamage = nil
end
if not r.auto then
r.auto = nil
end
end
Util.writeTable(RESOURCE_FILE, resources)
local function getItem(items, inItem, ignoreDamage)
for _,item in pairs(items) do
if item.name == inItem.name then
@@ -76,7 +59,7 @@ end
local function splitKey(key)
local t = Util.split(key, '(.-):')
local item = { }
if #t[#t] > 2 then
if #t[#t] > 8 then
item.nbtHash = table.remove(t)
end
item.damage = tonumber(table.remove(t))
@@ -108,14 +91,6 @@ local function uniqueKey(item)
return table.concat({ item.name, item.damage, item.nbtHash }, ':')
end
local function getName(item)
local detail = itemDB:get(itemDB:makeKey(item))
if detail then
return detail.displayName
end
return item.name .. ':' .. item.damage
end
local function mergeResources(t)
for _,v in pairs(resources) do
local item = getItem(t, v)
@@ -141,7 +116,7 @@ local function mergeResources(t)
for _,v in pairs(t) do
if not v.displayName then
v.displayName = getName(v)
v.displayName = itemDB:getName(v)
end
v.lname = v.displayName:lower()
end
@@ -209,7 +184,7 @@ local function addCraftingRequest(item, craftList, count)
local request = craftList[key]
if not craftList[key] then
request = { name = item.name, damage = item.damage, nbtHash = nbtHash, count = 0 }
request.displayName = getName(request)
request.displayName = itemDB:getName(request)
craftList[key] = request
end
request.count = request.count + count
@@ -221,7 +196,13 @@ local function craftItem(recipe, items, originalItem, craftList, count)
return
end
local toCraft = Craft.getCraftableAmount(recipe, count, items)
local missing = { }
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'
end
if toCraft > 0 then
Craft.craftRecipe(recipe, toCraft, chestAdapter)
@@ -265,7 +246,6 @@ local function craftItems(craftList, allItems)
if controller:isCrafting(item) then
item.status = '(crafting)'
else
local count = item.count
while count >= 1 do -- try to request smaller quantities until successful
local s, m = pcall(function()
@@ -311,6 +291,20 @@ local function jobMonitor(jobList)
{ heading = 'Status', key = 'status', width = mon.width - 10 },
},
})
function jobListGrid:getRowTextColor(row, selected)
if row.status == '(no recipe)'then
return colors.red
elseif row.statusCode == 'missing' then
return colors.yellow
end
return UI.Grid:getRowTextColor(row, selected)
end
jobListGrid:draw()
jobListGrid:sync()
end
local function getAutocraftItems()
@@ -331,21 +325,17 @@ local function getItemWithQty(items, res, ignoreDamage)
local item = getItem(items, res, ignoreDamage)
if item then
if item and ignoreDamage then
local count = 0
if ignoreDamage 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
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
item.count = count
end
item.count = count
end
return item
@@ -362,13 +352,17 @@ local function watchResources(items)
damage = res.damage,
nbtHash = res.nbtHash,
name = res.name,
displayName = getName(res),
displayName = itemDB:getName(res),
count = 0
}
end
if res.limit and item.count > res.limit then
chestAdapter:provide(res, item.count - res.limit, nil, config.trashDirection)
chestAdapter:provide(
{ name = item.name, damage = item.damage },
item.count - res.limit,
nil,
config.trashDirection)
elseif res.low and item.count < res.low then
if res.ignoreDamage then
@@ -396,6 +390,27 @@ local function watchResources(items)
return craftList
end
local function loadResources()
resources = Util.readTable(RESOURCE_FILE) or { }
for k,v in pairs(resources) do
Util.merge(v, splitKey(k))
end
end
local function saveResources()
local t = { }
for k,v in pairs(resources) do
v = Util.shallowCopy(v)
v.name = nil
v.damage = nil
v.nbtHash = nil
t[k] = v
end
Util.writeTable(RESOURCE_FILE, t)
end
local itemPage = UI.Page {
backgroundColor = colors.lightGray,
titleBar = UI.TitleBar {
@@ -404,11 +419,9 @@ local itemPage = UI.Page {
event = 'form_cancel',
backgroundColor = colors.green
},
displayName = UI.Window {
x = 2, y = 2, width = UI.term.width - 4, height = 3,
},
form = UI.Form {
x = 4, y = 5, height = 8, rex = -4,
x = 2, y = 3, height = 8, rex = -4,
margin = 1,
[1] = UI.TextEntry {
width = 7,
backgroundColor = colors.gray,
@@ -433,7 +446,7 @@ local itemPage = UI.Page {
},
[4] = UI.Chooser {
width = 7,
formLabel = 'Ignore Dmg', formKey = 'ignore_dmg',
formLabel = 'Ignore Dmg', formKey = 'ignoreDamage',
nochoice = 'No',
choices = {
{ name = 'Yes', value = true },
@@ -475,21 +488,11 @@ local itemPage = UI.Page {
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('\n%s', item.nbtHash)
end
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.titleBar.title = item.displayName or item.name
local devices = self.form[6].choices
Util.clear(devices)
@@ -518,7 +521,7 @@ function itemPage:eventHandler(event)
elseif event.type == 'form_complete' then
local values = self.form.values
local keys = { 'name', 'auto', 'low', 'limit', 'damage',
'nbtHash', 'ignoreDamage',
'nbtHash',
'rsControl', 'rsDevice', 'rsSide', }
local filtered = { }
@@ -544,10 +547,11 @@ function itemPage:eventHandler(event)
if values.ignoreDamage == true then
filtered.damage = 0
filtered.ignoreDamage = true
end
resources[uniqueKey(filtered)] = filtered
Util.writeTable(RESOURCE_FILE, resources)
saveResources()
UI:setPreviousPage()
@@ -778,7 +782,7 @@ local function learnRecipe(page)
Util.writeTable(RECIPES_FILE, recipes)
local displayName = getName(recipe[1])
local displayName = itemDB:getName(recipe[1])
listingPage.statusBar.filter:setValue(displayName)
listingPage.statusBar:timedStatus('Learned: ' .. displayName, 3)
@@ -896,6 +900,9 @@ function craftPage:eventHandler(event)
return true
end
loadResources()
clearGrid()
UI:setPages({
listing = listingPage,
item = itemPage,
@@ -906,10 +913,7 @@ UI:setPages({
UI:setPage(listingPage)
listingPage:setFocus(listingPage.statusBar.filter)
clearGrid()
jobMonitor()
jobListGrid:draw()
jobListGrid:sync()
Event.onInterval(5, function()
@@ -922,10 +926,8 @@ Event.onInterval(5, function()
else
local craftList = watchResources(items)
jobListGrid:setValues(craftList)
--jobListGrid:draw()
--jobListGrid:sync()
craftItems(craftList, items)
jobListGrid:setValues(craftList)
jobListGrid:update()
jobListGrid:draw()
jobListGrid:sync()

261
apps/music.lua Normal file
View File

@@ -0,0 +1,261 @@
require = requireInjector(getfenv(1))
local Event = require('event')
local UI = require('ui')
multishell.setTitle(multishell.getCurrent(), 'Music')
local radio = device.drive or error('No drive attached')
if radio.side ~= 'top' and radio.side ~= 'bottom' then
error('Disk drive must be above or below turtle')
end
if not turtle then
error('This program can only be run on a turtle')
end
if not device.monitor then
error('Monitor must be attached (3 wide x 1 tall')
end
local monitor = UI.Device({
deviceType = 'monitor',
textScale = 0.5,
})
UI:setDefaultDevice(monitor)
local page = UI.Page({
volume = 15,
stationName = UI.Text({
y = 2,
x = 2,
width = monitor.width - 14,
height = 3,
backgroundColor = colors.brown,
}),
seek = UI.Button({
y = 7,
x = 13,
height = 3,
event = 'seek',
text = ' >> ',
}),
play = UI.Button({
y = 7,
x = 2,
height = 3,
event = 'play',
text = '> / ll',
}),
louder = UI.Button({
y = 7,
x = monitor.width - 15,
width = 3,
height = 3,
event = 'louder',
text = '+',
}),
quiet = UI.Button({
y = 7,
x = monitor.width - 20,
event = 'quiet',
width = 3,
height = 3,
text = '-',
}),
volumeDisplay = UI.Text({
y = 3,
x = monitor.width - 9,
width = 4,
}),
volume1 = UI.Window({
y = monitor.height - 1,
x = monitor.width - 8,
height = 1,
width = 1,
color = colors.white
}),
volume2 = UI.Window({
y = monitor.height - 2,
x = monitor.width - 7,
height = 2,
width = 1,
color = colors.white
}),
volume3 = UI.Window({
y = monitor.height - 3,
x = monitor.width - 6,
height = 3,
width = 1,
color = colors.yellow
}),
volume4 = UI.Window({
y = monitor.height - 4,
x = monitor.width - 5,
height = 4,
width = 1,
color = colors.yellow,
}),
volume5 = UI.Window({
y = monitor.height - 5,
x = monitor.width - 4,
height = 5,
width = 1,
color = colors.orange,
}),
volume6 = UI.Window({
y = monitor.height - 6,
x = monitor.width - 3,
height = 6,
width = 1,
color = colors.orange,
}),
volume7 = UI.Window({
y = monitor.height - 7,
x = monitor.width - 2,
height = 7,
width = 1,
color = colors.red,
}),
volume8 = UI.Window({
y = monitor.height - 8,
x = monitor.width - 1,
height = 8,
width = 1,
color = colors.red,
})
})
page.volumeControls = {
page.volume1, page.volume2,
page.volume3, page.volume4,
page.volume5, page.volume6,
page.volume7, page.volume8,
}
function page:eventHandler(event)
if event.type == 'play' then
self:play(not self.playing)
elseif event.type == 'seek' then
self:seek()
self:play(true)
elseif event.type == 'louder' then
if self.playing then
self:setVolume(self.volume + 1)
end
elseif event.type == 'quiet' then
if self.playing then
self:setVolume(self.volume - 1)
end
end
end
function page:setVolume(volume, displayOnly)
volume = math.min(volume, 15)
volume = math.max(volume, 1)
self.volume = volume
volume = math.ceil(volume / 2)
for i = 1, volume do
self.volumeControls[i].backgroundColor =
self.volumeControls[i].color
end
for i = volume + 1, #self.volumeControls do
self.volumeControls[i].backgroundColor = colors.black
end
for i = 1, #self.volumeControls do
self.volumeControls[i]:clear()
end
local percent = math.ceil(self.volume / 15 * 100)
self.volumeDisplay.value = percent .. '%'
self.volumeDisplay:draw()
end
function page:seek()
local actions = {
top = {
suck = turtle.suckUp,
drop = turtle.dropUp,
},
bottom = {
suck = turtle.suckDown,
drop = turtle.dropDown,
},
}
local slot = turtle.selectOpenSlot()
actions[radio.side].suck()
repeat
slot = slot + 1
if (slot > 16) then
slot = 1
end
until turtle.getItemCount(slot) >= 1
turtle.select(slot)
actions[radio.side].drop()
self:updateStationName()
end
function page:play(onOff)
self.playing = onOff
if self.playing then
if not radio.hasAudio() then
self:seek()
end
self:updateStationName()
radio.playAudio()
Event.addNamedTimer('songTimer', 180, false, function()
if self.playing then
self:seek()
self:play(true)
self:sync()
end
end)
else
radio.stopAudio()
end
end
function page.stationName:draw()
self:clear()
self:centeredWrite(2, self.value)
end
function page:updateStationName()
local title = radio.getAudioTitle()
if title then
self.stationName.value = title
self.stationName:draw()
end
end
Event.onInterval(1, function()
if not page.playing then
if page.stationName.value == '' then
page:updateStationName()
else
page.stationName.value = ''
page.stationName:draw()
end
page:sync()
end
end)
page:play(true)
page:setVolume(page.volume, true)
UI:setPage(page)
turtle.status = 'Jamming'
UI:pullEvents()
turtle.status = 'idle'
page:play(false)
UI.term:reset()

View File

@@ -1,38 +1,34 @@
requireInjector(getfenv(1))
local Event = require('event')
local GPS = require('gps')
local Logger = require('logger')
local MEProvider = require('meProvider')
local Point = require('point')
local Socket = require('socket')
local Util = require('util')
local Event = require('event')
local GPS = require('gps')
local ChestAdapter = require('chestAdapter18')
local Point = require('point')
local Socket = require('socket')
local Util = require('util')
if not device.wireless_modem then
error('Modem is required')
end
Logger.setWirelessLogging()
if not turtle then
error('Can only be run on a turtle')
end
local blocks = { }
local meProvider = MEProvider()
local items = { }
local pickups = Util.readTable('pickup.tbl') or { }
local cells = Util.readTable('cells.tbl') or { }
local refills = Util.readTable('refills.tbl') or { }
local fluids = Util.readTable('fluids.tbl') or { }
local chestPt = turtle.loadLocation('chest')
local chargePt = turtle.loadLocation('charge')
local locations = Util.readTable('/usr/config/pickup') or {
pickups = { },
cells = { },
refills = { },
fluids = { },
}
local fuel = {
item = {
id = 'minecraft:coal',
dmg = 0,
name = 'minecraft:coal',
damage = 0,
},
qty = 64
}
@@ -51,14 +47,18 @@ turtle.setMoveCallback(function(action, pt)
end)
function refuel()
if turtle.getFuelLevel() < 5000 then
if turtle.getFuelLevel() < 5000 and locations.dropPt then
print('refueling')
turtle.status = 'refueling'
gotoPoint(chestPt, true)
dropOff(chestPt)
gotoPoint(locations.dropPt, true)
dropOff(locations.dropPt)
local chestAdapter = ChestAdapter({
wrapSide = 'bottom',
direction = 'up',
})
while turtle.getFuelLevel() < 5000 do
turtle.select(1)
meProvider:provide(fuel.item, fuel.qty, 1)
chestAdapter:provide(fuel.item, fuel.qty, 1)
turtle.refuel(64)
print(turtle.getFuelLevel())
os.sleep(1)
@@ -71,7 +71,7 @@ function pickUp(pt)
gotoPoint(pt, true)
while true do
if not turtle.selectOpenSlot() then
dropOff(chestPt)
dropOff(locations.dropPt)
gotoPoint(pt, true)
end
turtle.select(1)
@@ -85,16 +85,17 @@ function dropOff(pt)
if turtle.selectSlotWithItems() then
gotoPoint(pt, true)
turtle.emptyInventory(turtle.dropDown)
if pt == chestPt then
if pt == locations.dropPt then
print('refreshing items')
items = meProvider:refresh()
chestAdapter = ChestAdapter()
items = chestAdapter:refresh()
end
end
end
function gotoPoint(pt, doDetect)
slots = turtle.getInventory()
while not turtle.pathfind(pt, blocks) do
while not turtle.pathfind(pt, { blocks = blocks }) do
if turtle.abort then
error('aborted')
end
@@ -110,7 +111,7 @@ end
function checkCell(pt)
if not turtle.selectOpenSlot() then
dropOff(chestPt)
dropOff(locations.dropPt)
end
print('checking cell')
@@ -123,7 +124,7 @@ function checkCell(pt)
print('charging cell')
turtle.selectOpenSlot()
turtle.digDown()
gotoPoint(chargePt, true)
gotoPoint(locations.chargePt, true)
turtle.dropDown()
os.sleep(energy / 20000)
turtle.suckDown()
@@ -152,12 +153,13 @@ function fluid(points)
end
function refill(entry)
dropOff(chestPt)
dropOff(locations.dropPt)
turtle.status = 'refilling'
gotoPoint(chestPt)
gotoPoint(locations.dropPt)
local chestAdapter = ChestAdapter()
for _,item in pairs(entry.items) do
meProvider:provide(item, tonumber(item.qty), turtle.selectOpenSlot())
chestAdapter:provide(item, tonumber(item.qty), turtle.selectOpenSlot())
end
if turtle.selectSlotWithItems() then
@@ -179,7 +181,7 @@ function oldRefill(points)
end
end
dropOff(points.source)
dropOff(chestPt)
dropOff(locations.dropPt)
end
local function makeKey(pt)
@@ -199,8 +201,8 @@ local function pickupHost(socket)
if data.type == 'pickup' then
local key = makeKey(data.point)
pickups[key] = data.point
Util.writeTable('pickup.tbl', pickups)
locations.pickups[key] = data.point
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'added' })
elseif data.type == 'items' then
@@ -208,41 +210,36 @@ local function pickupHost(socket)
elseif data.type == 'refill' then
local key = makeKey(data.entry.point)
refills[key] = data.entry
Util.writeTable('refills.tbl', refills)
locations.refills[key] = data.entry
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'added' })
elseif data.type == 'setPickup' then
chestPt = data.point
-- fix
turtle.storeLocation('chest', chestPt)
locations.dropPt = data.point
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'Location set' })
elseif data.type == 'setRecharge' then
chargePt = data.point
-- fix
turtle.storeLocation('charge', chargePt)
locations.chargePt = data.point
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'Location set' })
elseif data.type == 'charge' then
local key = makeKey(data.point)
cells[key] = data.point
Util.writeTable('cells.tbl', cells)
locations.cells[key] = data.point
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'added' })
elseif data.type == 'fluid' then
elseif data.type == 'clear' then
local key = makeKey(data.point)
refills[key] = nil
cells[key] = nil
fluids[key] = nil
pickups[key] = nil
locations.refills[key] = nil
locations.cells[key] = nil
locations.fluids[key] = nil
locations.pickups[key] = nil
Util.writeTable('refills.tbl', refills)
Util.writeTable('cells.tbl', cells)
Util.writeTable('fluids.tbl', fluids)
Util.writeTable('pickup.tbl', pickups)
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'cleared' })
else
@@ -303,15 +300,22 @@ end
Event.addRoutine(function()
if not turtle.enableGPS() then
error('turtle: No GPS found')
end
refuel()
while true do
if chestPt then
eachClosestEntry(pickups, pickUp)
eachEntry(refills, refill)
if locations.dropPt then
eachClosestEntry(locations.pickups, pickUp)
eachEntry(locations.refills, refill)
refuel()
end
eachEntry(fluids, fluid)
if chargePt then
eachEntry(cells, checkCell)
dropOff(locations.dropPt)
eachEntry(locations.fluids, fluid)
if locations.chargePt then
eachEntry(locations.cells, checkCell)
end
print('sleeping')
turtle.status = 'sleeping'
@@ -327,11 +331,6 @@ end)
turtle.run(function()
if not turtle.enableGPS() then
error('turtle: No GPS found')
end
refuel()
Event.pullEvents()
end)

View File

@@ -18,11 +18,12 @@ local mainPage = UI.Page({
menu = UI.Menu({
centered = true,
y = 2,
height = 8,
menuItems = {
{ prompt = 'Pickup', event = 'pickup', help = 'Pickup items from this location' },
{ prompt = 'Charge cell', event = 'charge', help = 'Recharge this cell' },
{ prompt = 'Refill', event = 'refill', help = 'Recharge this cell' },
{ prompt = 'Set pickup location', event = 'setPickup', help = 'Recharge this cell' },
{ prompt = 'Set drop off location', event = 'setPickup', help = 'Recharge this cell' },
{ prompt = 'Set recharge location', event = 'setRecharge', help = 'Recharge this cell' },
{ prompt = 'Clear', event = 'clear', help = 'Remove this location' },
},
@@ -89,7 +90,7 @@ local function sendCommand(cmd)
end
local function getPoint()
local gpt = GPS.getPoint()
local gpt = GPS.getPoint(2)
if not gpt then
mainPage.statusBar:timedStatus('Unable to get location', 3)
end

View File

@@ -251,143 +251,19 @@ local levelScript = [[
requireInjector(getfenv(1))
local Point = require('point')
local Level = require('turtle.level')
local Util = require('util')
local checkedNodes = { }
local nodes = { }
local box = { }
local function inBox(pt, box)
return pt.x >= box.x and
pt.y >= box.y and
pt.z >= box.z and
pt.x <= box.ex and
pt.y <= box.ey and
pt.z <= box.ez
end
local function toKey(pt)
return table.concat({ pt.x, pt.y, pt.z }, ':')
end
local function addNode(node)
for i = 0, 5 do
local hi = turtle.getHeadingInfo(i)
local testNode = { x = node.x + hi.xd, y = node.y + hi.yd, z = node.z + hi.zd }
if inBox(testNode, box) then
local key = toKey(testNode)
if not checkedNodes[key] then
nodes[key] = testNode
end
end
end
end
local function dig(action)
local directions = {
top = 'up',
bottom = 'down',
}
-- convert to up, down, north, south, east, west
local direction = directions[action.side] or
turtle.getHeadingInfo(turtle.point.heading).direction
local hi = turtle.getHeadingInfo(direction)
local node = { x = turtle.point.x + hi.xd, y = turtle.point.y + hi.yd, z = turtle.point.z + hi.zd }
if inBox(node, box) then
local key = toKey(node)
checkedNodes[key] = true
nodes[key] = nil
if action.dig() then
addNode(node)
repeat until not action.dig() -- sand, etc
return true
end
end
end
local function move(action)
if action == 'turn' then
dig(turtle.getAction('forward'))
elseif action == 'up' then
dig(turtle.getAction('up'))
elseif action == 'down' then
dig(turtle.getAction('down'))
elseif action == 'back' then
dig(turtle.getAction('up'))
dig(turtle.getAction('down'))
end
end
local function getAdjacentPoint(pt)
local t = { }
table.insert(t, pt)
for i = 0, 5 do
local hi = turtle.getHeadingInfo(i)
local heading
if i < 4 then
heading = (hi.heading + 2) % 4
end
table.insert(t, { x = pt.x + hi.xd, z = pt.z + hi.zd, y = pt.y + hi.yd, heading = heading })
end
return Point.closest2(turtle.getPoint(), t)
end
local function level()
box.x = math.min(data.startPt.x, data.endPt.x)
box.y = math.min(data.startPt.y, data.endPt.y)
box.z = math.min(data.startPt.z, data.endPt.z)
box.ex = math.max(data.startPt.x, data.endPt.x)
box.ey = math.max(data.startPt.y, data.endPt.y)
box.ez = math.max(data.startPt.z, data.endPt.z)
turtle.pathfind(data.firstPt)
turtle.setPolicy("attack", { dig = dig }, "assuredMove")
turtle.setMoveCallback(move)
repeat
local key = toKey(turtle.point)
checkedNodes[key] = true
nodes[key] = nil
dig(turtle.getAction('down'))
dig(turtle.getAction('up'))
dig(turtle.getAction('forward'))
print(string.format('%d nodes remaining', Util.size(nodes)))
if Util.size(nodes) == 0 then
break
end
local node = Point.closest2(turtle.point, nodes)
node = getAdjacentPoint(node)
if not turtle.gotoPoint(node) then
break
end
until turtle.abort
turtle.resetState()
end
local s, m = turtle.run(function()
turtle.status = 'Leveling'
if turtle.enableGPS() then
local pt = Util.shallowCopy(turtle.point)
local s, m = pcall(level)
local s, m = pcall(function()
Level(data.startPt, data.endPt, data.firstPt)
end)
turtle.pathfind(pt)
if not s and m then
@@ -446,7 +322,7 @@ end
function page:runFunction(id, script)
Util.writeFile('script.tmp', script)
--Util.writeFile('script.tmp', script)
self.notification:info('Connecting')
local fn, msg = loadstring(script, 'script')
if not fn then

File diff suppressed because it is too large Load Diff