1
0
mirror of https://github.com/kepler155c/opus synced 2024-06-14 17:29:59 +00:00

bit of everything

This commit is contained in:
kepler155c@gmail.com 2017-07-23 22:37:07 -04:00
parent 027f386ed1
commit f8bcf90a6b
30 changed files with 866 additions and 502 deletions

View File

@ -14,7 +14,6 @@ local keys = Util.transpose({
}) })
function ChestProvider:init(args) function ChestProvider:init(args)
local defaults = { local defaults = {
items = { }, items = { },
name = 'chest', name = 'chest',
@ -43,12 +42,10 @@ function ChestProvider:getCachedItemDetails(item, k)
if not detail then if not detail then
return return
end end
-- NOT SUFFICIENT
if detail.name ~= item.name then if detail.name ~= item.name then
return return
end end
if detail.maxDamage and detail.maxDamage > 0 and detail.damage > 0 then
detail.displayName = detail.displayName .. ' (damaged)'
end
for _,k in ipairs(Util.keys(detail)) do for _,k in ipairs(Util.keys(detail)) do
if not keys[k] then if not keys[k] then
@ -135,8 +132,8 @@ function ChestProvider:provide(item, qty, slot, direction)
end end
end end
function ChestProvider:extract(slot, qty) function ChestProvider:extract(slot, qty, toSlot)
self.pushItems(self.direction, slot, qty) self.pushItems(self.direction, slot, qty, toSlot)
end end
function ChestProvider:insert(slot, qty) function ChestProvider:insert(slot, qty)

View File

@ -1,25 +1,17 @@
local Util = require('util') local Util = require('util')
local Process = require('process')
local Event = { local Event = {
uid = 1, -- unique id for handlers uid = 1, -- unique id for handlers
routines = { },
handlers = { namedTimers = { } },
terminate = false,
} }
local eventHandlers = {
namedTimers = {}
}
-- debug purposes
function Event.getHandlers()
return eventHandlers
end
function Event.addHandler(type, f) function Event.addHandler(type, f)
local event = eventHandlers[type] local event = Event.handlers[type]
if not event then if not event then
event = {} event = { handlers = { } }
event.handlers = {} Event.handlers[type] = event
eventHandlers[type] = event
end end
local handler = { local handler = {
@ -35,7 +27,7 @@ end
function Event.removeHandler(h) function Event.removeHandler(h)
if h and h.event then if h and h.event then
eventHandlers[h.event].handlers[h.uid] = nil Event.handlers[h.event].handlers[h.uid] = nil
end end
end end
@ -49,11 +41,11 @@ end
function Event.addNamedTimer(name, interval, recurring, f) function Event.addNamedTimer(name, interval, recurring, f)
Event.cancelNamedTimer(name) Event.cancelNamedTimer(name)
eventHandlers.namedTimers[name] = Event.addTimer(interval, recurring, f) Event.handlers.namedTimers[name] = Event.addTimer(interval, recurring, f)
end end
function Event.getNamedTimer(name) function Event.getNamedTimer(name)
return eventHandlers.namedTimers[name] return Event.handlers.namedTimers[name]
end end
function Event.cancelNamedTimer(name) function Event.cancelNamedTimer(name)
@ -64,11 +56,6 @@ function Event.cancelNamedTimer(name)
end end
end end
function Event.isTimerActive(timer)
return timer.enabled and
os.clock() < timer.start + timer.interval
end
function Event.addTimer(interval, recurring, f) function Event.addTimer(interval, recurring, f)
local timer = Event.addHandler('timer', local timer = Event.addHandler('timer',
function(t, id) function(t, id)
@ -81,7 +68,6 @@ function Event.addTimer(interval, recurring, f)
end end
if t.recurring then if t.recurring then
t.fired = false t.fired = false
t.start = os.clock()
t.timerId = os.startTimer(t.interval) t.timerId = os.startTimer(t.interval)
else else
Event.removeHandler(t) Event.removeHandler(t)
@ -91,103 +77,121 @@ function Event.addTimer(interval, recurring, f)
timer.cf = f timer.cf = f
timer.interval = interval timer.interval = interval
timer.recurring = recurring timer.recurring = recurring
timer.start = os.clock()
timer.enabled = true timer.enabled = true
timer.timerId = os.startTimer(interval) timer.timerId = os.startTimer(interval)
return timer return timer
end end
function Event.removeTimer(h) function Event.onInterval(interval, f)
Event.removeHandler(h) return Event.addTimer(interval, true, f)
end end
function Event.blockUntilEvent(event, timeout) function Event.onTimeout(timeout, f)
return Event.waitForEvent(event, timeout, os.pullEvent) return Event.addTimer(timeout, false, f)
end end
function Event.waitForEvent(event, timeout, pullEvent) function Event.waitForEvent(event, timeout)
pullEvent = pullEvent or Event.pullEvent
local timerId = os.startTimer(timeout) local timerId = os.startTimer(timeout)
repeat repeat
local e, p1, p2, p3, p4 = pullEvent() local e, p1, p2, p3, p4 = os.pullEvent()
if e == event then if e == event then
return e, p1, p2, p3, p4 return e, p1, p2, p3, p4
end end
until e == 'timer' and p1 == timerId until e == 'timer' and p1 == timerId
end end
local exitPullEvents = false function Event.addRoutine(routine)
local r = { co = coroutine.create(routine) }
local function _pullEvents() local s, m = coroutine.resume(r.co)
while true do if not s then
local e = { os.pullEvent() } error(m or 'Error processing routine')
Event.processEvent(e)
end end
end Event.routines[r] = true
r.filter = m
function Event.sleep(t) return r
local timerId = os.startTimer(t or 0)
repeat
local event, id = Event.pullEvent()
until event == 'timer' and id == timerId
end
function Event.addThread(fn)
return Process:addThread(fn)
end end
function Event.pullEvents(...) function Event.pullEvents(...)
local routines = { ... }
if #routines > 0 then for _, r in ipairs({ ... }) do
Process:addThread(_pullEvents) Event.addRoutine(r)
for _, routine in ipairs(routines) do
Process:addThread(routine)
end
while true do
local e = Process:pullEvent()
if exitPullEvents or e == 'terminate' then
break
end
end
else
while true do
local e = { os.pullEventRaw() }
Event.processEvent(e)
if exitPullEvents or e[1] == 'terminate' then
break
end
end
end end
repeat
local e = Event.pullEvent()
until e[1] == 'terminate'
end end
function Event.exitPullEvents() function Event.exitPullEvents()
exitPullEvents = true Event.terminate = true
os.sleep(0) os.sleep(0)
end end
function Event.pullEvent(eventType) function Event.pullEvent(eventType)
local e = { os.pullEventRaw(eventType) }
return Event.processEvent(e) while true do
local e = { os.pullEventRaw() }
local routines = Util.keys(Event.routines)
for _, r in ipairs(routines) do
if not r.filter or r.filter == e[1] then
local s, m = coroutine.resume(r.co, table.unpack(e))
if not s and e[1] ~= 'terminate' then
debug({s, m})
debug(r)
error(m or 'Error processing event')
end
if coroutine.status(r.co) == 'dead' then
r.co = nil
Event.routines[r] = nil
else
r.filter = m
end
end
end
Event.processEvent(e)
if Event.terminate or e[1] == 'terminate' then
Event.terminate = false
return { 'terminate' }
end
if not eventType or e[1] == eventType then
return e
end
end
end end
function Event.processEvent(pe) function Event.processEvent(pe)
local e, p1, p2, p3, p4, p5 = unpack(pe) local e, p1, p2, p3, p4, p5 = unpack(pe)
local event = eventHandlers[e] local event = Event.handlers[e]
if event then if event then
local keys = Util.keys(event.handlers) local keys = Util.keys(event.handlers)
for _,key in pairs(keys) do for _,key in pairs(keys) do
local h = event.handlers[key] local h = event.handlers[key]
if h then if h and not h.co then
h.f(h, p1, p2, p3, p4, p5) local co = coroutine.create(function()
h.f(h, p1, p2, p3, p4, p5)
end)
local s, m = coroutine.resume(co)
if not s then
debug({s, m})
debug(h)
error(m or 'Error processing ' .. e)
elseif coroutine.status(co) ~= 'dead' then
h.co = co
h.filter = m
Event.routines[h] = true
end
end end
end end
end end
return e, p1, p2, p3, p4, p5 return e, p1, p2, p3, p4, p5
end end
Event.on = Event.addHandler
Event.off = Event.removeHandler
return Event return Event

View File

@ -12,9 +12,9 @@ local PASTEBIN_URL = 'http://pastebin.com/raw'
local GIT_URL = 'https://raw.githubusercontent.com' local GIT_URL = 'https://raw.githubusercontent.com'
local function standardSearcher(modname, env, shell) local function standardSearcher(modname, env, shell)
if package.loaded[modname] then if _G.package.loaded[modname] then
return function() return function()
return package.loaded[modname] return _G.package.loaded[modname]
end end
end end
end end
@ -33,7 +33,7 @@ end
local function pathSearcher(modname, env, shell) local function pathSearcher(modname, env, shell)
local fname = modname:gsub('%.', '/') .. '.lua' local fname = modname:gsub('%.', '/') .. '.lua'
for dir in string.gmatch(package.path, "[^:]+") do for dir in string.gmatch(_G.package.path, "[^:]+") do
local path = fs.combine(dir, fname) local path = fs.combine(dir, fname)
if fs.exists(path) and not fs.isDir(path) then if fs.exists(path) and not fs.isDir(path) then
return loadfile(path, env) return loadfile(path, env)
@ -109,7 +109,7 @@ local function urlSearcher(modname, env, shell)
local fname = modname:gsub('%.', '/') .. '.lua' local fname = modname:gsub('%.', '/') .. '.lua'
if fname:sub(1, 1) ~= '/' then if fname:sub(1, 1) ~= '/' then
for entry in string.gmatch(package.upath, "[^;]+") do for entry in string.gmatch(_G.package.upath, "[^;]+") do
local url = entry .. '/' .. fname local url = entry .. '/' .. fname
local c = loadUrl(url) local c = loadUrl(url)
if c then if c then
@ -150,7 +150,7 @@ local function requireWrapper(env)
return loaded[modname] return loaded[modname]
end end
for _,searcher in ipairs(package.loaders) do for _,searcher in ipairs(_G.package.loaders) do
local fn, msg = searcher(modname, env, shell) local fn, msg = searcher(modname, env, shell)
if fn then if fn then
local module, msg = fn(modname, env) local module, msg = fn(modname, env)

View File

@ -1,6 +1,6 @@
local TableDB = require('tableDB') local TableDB = require('tableDB')
local itemDB = TableDB({ fileName = 'usr/config/items.db' }) local itemDB = TableDB({ fileName = 'usr/etc/items.db' })
function itemDB:get(key) function itemDB:get(key)
@ -13,6 +13,9 @@ function itemDB:get(key)
if key[2] ~= 0 then if key[2] ~= 0 then
item = TableDB.get(self, { key[1], 0, key[3] }) item = TableDB.get(self, { key[1], 0, key[3] })
if item and item.maxDamage > 0 then if item and item.maxDamage > 0 then
item = Util.shallowCopy(item)
item.damage = key[2]
item.displayName = string.format('%s (damage: %d)', item.displayName, item.damage)
return item return item
end end
end end

View File

@ -50,7 +50,12 @@ function Peripheral.addDevice(deviceList, side)
name = uniqueName name = uniqueName
end end
deviceList[name] = peripheral.wrap(side) local s, m pcall(function() deviceList[name] = peripheral.wrap(side) end)
if not s and m then
printError('wrap failed')
printError(m)
end
if deviceList[name] then if deviceList[name] then
Util.merge(deviceList[name], { Util.merge(deviceList[name], {
name = name, name = name,

View File

@ -4,13 +4,19 @@ function Point.copy(pt)
return { x = pt.x, y = pt.y, z = pt.z } return { x = pt.x, y = pt.y, z = pt.z }
end end
function Point.same(pta, ptb)
return pta.x == ptb.x and
pta.y == ptb.y and
pta.z == ptb.z
end
function Point.subtract(a, b) function Point.subtract(a, b)
a.x = a.x - b.x a.x = a.x - b.x
a.y = a.y - b.y a.y = a.y - b.y
a.z = a.z - b.z a.z = a.z - b.z
end end
-- real distance -- Euclidian distance
function Point.pythagoreanDistance(a, b) function Point.pythagoreanDistance(a, b)
return math.sqrt( return math.sqrt(
math.pow(a.x - b.x, 2) + math.pow(a.x - b.x, 2) +
@ -18,7 +24,7 @@ function Point.pythagoreanDistance(a, b)
math.pow(a.z - b.z, 2)) math.pow(a.z - b.z, 2))
end end
-- turtle distance -- turtle distance (manhattan)
function Point.turtleDistance(a, b) function Point.turtleDistance(a, b)
if a.y and b.y then if a.y and b.y then
return math.abs(a.x - b.x) + return math.abs(a.x - b.x) +
@ -40,6 +46,35 @@ function Point.calculateTurns(ih, oh)
return 1 return 1
end end
function Point.calculateHeading(pta, ptb)
local heading
if (pta.heading % 2) == 0 and pta.z ~= ptb.z then
if ptb.z > pta.z then
heading = 1
else
heading = 3
end
elseif (pta.heading % 2) == 1 and pta.x ~= ptb.x then
if ptb.x > pta.x then
heading = 0
else
heading = 2
end
elseif pta.heading == 0 and pta.x > ptb.x then
heading = 2
elseif pta.heading == 2 and pta.x < ptb.x then
heading = 0
elseif pta.heading == 1 and pta.z > ptb.z then
heading = 3
elseif pta.heading == 3 and pta.z < ptb.z then
heading = 1
end
return heading or pta.heading
end
-- Calculate distance to location including turns -- Calculate distance to location including turns
-- also returns the resulting heading -- also returns the resulting heading
function Point.calculateMoves(pta, ptb, distance) function Point.calculateMoves(pta, ptb, distance)
@ -88,6 +123,32 @@ function Point.closest(reference, pts)
return lpt return lpt
end end
-- find the closest block
-- * favor same plane
-- * going backwards only if the dest is above or below
function Point.closest2(reference, pts)
local lpt, lm -- lowest
for _,pt in pairs(pts) do
local m = Point.turtleDistance(reference, pt)
local h = Point.calculateHeading(reference, pt)
local t = Point.calculateTurns(reference.heading, h)
if pt.y ~= reference.y then -- try and stay on same plane
m = m + .01
end
if t ~= 2 or pt.y == reference.y then
m = m + t
if t > 0 then
m = m + .01
end
end
if not lm or m < lm then
lpt = pt
lm = m
end
end
return lpt
end
function Point.adjacentPoints(pt) function Point.adjacentPoints(pt)
local pts = { } local pts = { }

View File

@ -48,9 +48,6 @@ function RefinedProvider:getCachedItemDetails(item)
return return
end end
Util.merge(detail, meta) Util.merge(detail, meta)
if detail.maxDamage and detail.maxDamage > 0 and detail.damage > 0 then
detail.displayName = detail.displayName .. ' (damaged)'
end
detail.lname = detail.displayName:lower() detail.lname = detail.displayName:lower()
local t = { } local t = { }

View File

@ -100,15 +100,15 @@ function Schematic:parse(a, h, containsName, spinner)
local i4 = h:readbyte(h) local i4 = h:readbyte(h)
local i = bit.blshift(i1, 24) + bit.blshift(i2, 16) + bit.blshift(i3, 8) + i4 local i = bit.blshift(i1, 24) + bit.blshift(i2, 16) + bit.blshift(i3, 8) + i4
if not self.length or not self.width then if name == "Blocks" then
self:discardBytes(h,i, spinner)
self.twopass = true
elseif name == "Blocks" then
for i = 1, i do for i = 1, i do
local id = h:readbyte(h) local id = h:readbyte(h)
self:assignCoord(i, id) if id > 0 then
table.insert(self.blocks, {
id = id,
index = i,
})
end
if (i % 1000) == 0 then if (i % 1000) == 0 then
spinner:spin() spinner:spin()
end end
@ -269,15 +269,36 @@ function Schematic:loadpass(fh, spinner)
break break
end end
self:parse(a, fh, true, spinner) self:parse(a, fh, true, spinner)
if self.twopass and self.width and self.length then
break
end
spinner:spin() spinner:spin()
end end
fh:close() fh:close()
print('Assigning coords ')
local index = 1
for _, b in ipairs(self.blocks) do
while index < b.index do
self.x = self.x + 1
if self.x >= self.width then
self.x = 0
self.z = self.z + 1
end
if self.z >= self.length then
self.z = 0
self.y = self.y + 1
end
if self.y >= self.height then
self.height = self.y + 1
end
index = index + 1
end
b.x = self.x
b.y = self.y
b.z = self.z
spinner:spin()
end
self:assignDamages(spinner) self:assignDamages(spinner)
self.damages = nil self.damages = nil
@ -313,22 +334,9 @@ function Schematic:load(filename)
self:checkFileType(f) self:checkFileType(f)
print('Initial pass ') print('Loading blocks ')
self:loadpass(f, spinner) self:loadpass(f, spinner)
if self.twopass then
self.twopass = nil
self.blocks = { }
self.damages = { }
self.originalBlocks = { }
self.x, self.y, self.z = 0, 0, 0
self.height = 0
self.index = 1
print('Second pass ')
self:loadpass(f, spinner)
end
self.rowIndex = { } self.rowIndex = { }
for k,b in ipairs(self.blocks) do for k,b in ipairs(self.blocks) do
local ri = self.rowIndex[b.y] local ri = self.rowIndex[b.y]
@ -342,42 +350,12 @@ function Schematic:load(filename)
self.cache = Util.readTable('usr/builder/' .. self.filename .. '.cache') or { } self.cache = Util.readTable('usr/builder/' .. self.filename .. '.cache') or { }
end end
function Schematic:assignCoord(i, id)
if id > 0 then
table.insert(self.blocks, {
id = id,
index = i,
x = self.x,
z = self.z,
y = self.y,
})
end
self.x = self.x + 1
if self.x >= self.width then
self.x = 0
self.z = self.z + 1
end
if self.z >= self.length then
self.z = 0
self.y = self.y + 1
end
if self.y >= self.height then
self.height = self.y + 1
end
end
function Schematic:assignDamages(spinner) function Schematic:assignDamages(spinner)
print('Assigning damages') print('Assigning damages')
local i = 0
for _,b in pairs(self.blocks) do for _,b in pairs(self.blocks) do
b.dmg = self.damages[b.index] or 0 b.dmg = self.damages[b.index] or 0
i = i + 1 spinner:spin()
if (i % 1000) == 0 then
spinner:spin()
end
end end
end end
@ -849,6 +827,7 @@ function Schematic:getComputedBlock(i)
-- has this level been computed ? -- has this level been computed ?
if not self.rowIndex[b.y].loaded then if not self.rowIndex[b.y].loaded then
-- compute each level up til this one (unless saved in cache) -- compute each level up til this one (unless saved in cache)
for y = 0, b.y - 1 do for y = 0, b.y - 1 do
if not self.cache[y] then if not self.cache[y] then
self:determineBlockPlacement(y) self:determineBlockPlacement(y)
@ -858,7 +837,6 @@ function Schematic:getComputedBlock(i)
-- get the block now at the computed location -- get the block now at the computed location
b = self.blocks[i] b = self.blocks[i]
end end
return b return b
end end

View File

@ -67,7 +67,7 @@ function Manager:init(args)
local mouseDragged = false local mouseDragged = false
local pages = { } local pages = { }
Event.addHandler('term_resize', function(h, side) Event.on('term_resize', function(h, side)
if self.currentPage then if self.currentPage then
-- the parent doesn't have any children set... -- the parent doesn't have any children set...
-- that's why we have to resize both the parent and the current page -- that's why we have to resize both the parent and the current page
@ -81,7 +81,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('mouse_scroll', function(h, direction, x, y) Event.on('mouse_scroll', function(h, direction, x, y)
if self.target then if self.target then
local event = self:pointToChild(self.target, x, y) local event = self:pointToChild(self.target, x, y)
local directions = { local directions = {
@ -97,7 +97,7 @@ function Manager:init(args)
end) end)
-- this should be moved to the device ! -- this should be moved to the device !
Event.addHandler('monitor_touch', function(h, side, x, y) Event.on('monitor_touch', function(h, side, x, y)
if self.currentPage then if self.currentPage then
if self.currentPage.parent.device.side == side then if self.currentPage.parent.device.side == side then
self:click(1, x, y) self:click(1, x, y)
@ -105,7 +105,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('mouse_click', function(h, button, x, y) Event.on('mouse_click', function(h, button, x, y)
mouseDragged = false mouseDragged = false
if button == 1 and shift and control then -- debug hack if button == 1 and shift and control then -- debug hack
@ -123,7 +123,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('mouse_up', function(h, button, x, y) Event.on('mouse_up', function(h, button, x, y)
if self.currentPage and not mouseDragged then if self.currentPage and not mouseDragged then
if not self.currentPage.parent.device.side then if not self.currentPage.parent.device.side then
@ -132,7 +132,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('mouse_drag', function(h, button, x, y) Event.on('mouse_drag', function(h, button, x, y)
mouseDragged = true mouseDragged = true
if self.target then if self.target then
@ -146,7 +146,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('paste', function(h, text) Event.on('paste', function(h, text)
if clipboard.isInternal() then if clipboard.isInternal() then
text = clipboard.getData() text = clipboard.getData()
end end
@ -156,7 +156,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('char', function(h, ch) Event.on('char', function(h, ch)
control = false control = false
if self.currentPage then if self.currentPage then
self:inputEvent(self.currentPage.focused, { type = 'key', key = ch }) self:inputEvent(self.currentPage.focused, { type = 'key', key = ch })
@ -164,7 +164,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('key_up', function(h, code) Event.on('key_up', function(h, code)
if code == keys.leftCtrl or code == keys.rightCtrl then if code == keys.leftCtrl or code == keys.rightCtrl then
control = false control = false
elseif code == keys.leftShift or code == keys.rightShift then elseif code == keys.leftShift or code == keys.rightShift then
@ -172,7 +172,7 @@ function Manager:init(args)
end end
end) end)
Event.addHandler('key', function(h, code) Event.on('key', function(h, code)
local ch = keys.getName(code) local ch = keys.getName(code)
if not ch then if not ch then
return return
@ -1282,6 +1282,8 @@ function UI.Device:runTransitions(transitions, canvas)
if Util.empty(transitions) then if Util.empty(transitions) then
break break
end end
os.sleep(0)
--[[
local timerId = os.startTimer(0) local timerId = os.startTimer(0)
while true do while true do
local e = { os.pullEvent() } local e = { os.pullEvent() }
@ -1290,10 +1292,11 @@ function UI.Device:runTransitions(transitions, canvas)
end end
table.insert(queue, e) table.insert(queue, e)
end end
--]]
end end
for _, e in ipairs(queue) do -- for _, e in ipairs(queue) do
Event.processEvent(e) -- Event.processEvent(e)
end -- end
end end
function UI.Device:sync() function UI.Device:sync()

View File

@ -116,23 +116,20 @@ function page.grid:getDisplayValues(row)
return row return row
end end
Event.addThread(function() Event.onInterval(1, function()
while true do page.grid:update()
page.grid:update() page.grid:draw()
page.grid:draw() page:sync()
page:sync()
os.sleep(1)
end
end) end)
Event.addHandler('device_attach', function(h, deviceName) Event.on('device_attach', function(h, deviceName)
if deviceName == 'wireless_modem' then if deviceName == 'wireless_modem' then
page.notification:success('Modem connected') page.notification:success('Modem connected')
page:sync() page:sync()
end end
end) end)
Event.addHandler('device_detach', function(h, deviceName) Event.on('device_detach', function(h, deviceName)
if deviceName == 'wireless_modem' then if deviceName == 'wireless_modem' then
page.notification:error('Wireless modem not attached') page.notification:error('Wireless modem not attached')
page:sync() page:sync()

View File

@ -532,34 +532,30 @@ if not fs.exists(GROUPS_PATH) then
fs.makeDir(GROUPS_PATH) fs.makeDir(GROUPS_PATH)
end end
Event.addHandler('network_attach', function() Event.on('network_attach', function()
if mainPage.enabled then if mainPage.enabled then
mainPage:draw() mainPage:draw()
end end
end) end)
Event.addHandler('network_detach', function() Event.on('network_detach', function()
if mainPage.enabled then if mainPage.enabled then
mainPage:draw() mainPage:draw()
end end
end) end)
function statusUpdate() Event.onInterval(1, function()
while true do if mainPage.enabled then
if mainPage.enabled then local selected = mainPage.computers:getSelected()
local selected = mainPage.computers:getSelected() if selected then
if selected then local computer = _G.network[selected.id]
local computer = _G.network[selected.id] mainPage.statusBar.values = { computer }
mainPage.statusBar.values = { computer } mainPage.statusBar:draw()
mainPage.statusBar:draw() mainPage:sync()
mainPage:sync()
end
end end
os.sleep(1)
end end
end end)
UI:setPage(mainPage) UI:setPage(mainPage)
UI:pullEvents()
Event.pullEvents(statusUpdate)
UI.term:reset() UI.term:reset()

View File

@ -52,7 +52,7 @@ function page.grid:getDisplayValues(row)
if elapsed < 60 then if elapsed < 60 then
row.timestamp = string.format("%ds", math.floor(elapsed)) row.timestamp = string.format("%ds", math.floor(elapsed))
else else
row.timestamp = string.format("%fm", math.floor(elapsed/6)/10) row.timestamp = string.format("%sm", math.floor(elapsed/6)/10)
end end
if row.isDead then if row.isDead then
row.status = 'error' row.status = 'error'

View File

@ -2,7 +2,7 @@ require = requireInjector(getfenv(1))
local UI = require('ui') local UI = require('ui')
local Socket = require('socket') local Socket = require('socket')
local Terminal = require('terminal') local Terminal = require('terminal')
local TableDB = require('tableDB') local itemDB = require('itemDB')
multishell.setTitle(multishell.getCurrent(), 'Turtles') multishell.setTitle(multishell.getCurrent(), 'Turtles')
UI.Button.defaults.focusIndicator = ' ' UI.Button.defaults.focusIndicator = ' '
@ -31,12 +31,6 @@ local policies = {
{ label = 'turtleSafe' }, { label = 'turtleSafe' },
} }
local itemInfoDB = TableDB({
fileName = 'items.db'
})
itemInfoDB:load()
local page = UI.Page { local page = UI.Page {
--[[ --[[
policy = UI.Chooser { policy = UI.Chooser {
@ -177,7 +171,7 @@ function page.coords:draw()
self:clear() self:clear()
self:setCursorPos(1, 1) self:setCursorPos(1, 1)
local ind = 'GPS' local ind = 'GPS'
if t.coordSystem ~= 'GPS' then if not t.point.gps then
ind = 'REL' ind = 'REL'
end end
self:print(string.format('%s : %d,%d,%d\nFuel: %s\n', self:print(string.format('%s : %d,%d,%d\nFuel: %s\n',
@ -204,7 +198,7 @@ function page.tabs.inventory:draw()
v.selected = true v.selected = true
end end
if v.id then if v.id then
local item = itemInfoDB:get({ v.id, v.dmg }) local item = itemDB:get({ v.id, v.dmg })
if item then if item then
v.id = item.displayName v.id = item.displayName
else else

View File

@ -41,6 +41,7 @@ local Builder = {
resourceSlots = 14, resourceSlots = 14,
facing = 'south', facing = 'south',
confirmFacing = false, confirmFacing = false,
wrenchSucks = false,
} }
local pistonFacings local pistonFacings
@ -95,6 +96,7 @@ function subDB:seedDB()
[ "minecraft:wall_banner:0" ] = "minecraft:banner:0", [ "minecraft:wall_banner:0" ] = "minecraft:banner:0",
[ "minecraft:standing_banner:0" ] = "minecraft:banner:0", [ "minecraft:standing_banner:0" ] = "minecraft:banner:0",
[ "minecraft:tripwire:0" ] = "minecraft:string:0", [ "minecraft:tripwire:0" ] = "minecraft:string:0",
[ "minecraft:pumpkin_stem:0" ] = "minecraft:pumpkin_seeds:0",
} }
self.dirty = true self.dirty = true
self:flush() self:flush()
@ -266,7 +268,7 @@ function Builder:getAirResupplyList(blockIndex)
local fuel = subDB:getSubstitutedItem(Builder.fuelItem.id, Builder.fuelItem.dmg) local fuel = subDB:getSubstitutedItem(Builder.fuelItem.id, Builder.fuelItem.dmg)
slots[15] = { slots[15] = {
id = 'ironchest:BlockIronChest', -- 'minecraft:chest', id = 'minecraft:chest', --'ironchest:BlockIronChest', --
dmg = 0, dmg = 0,
qty = 0, qty = 0,
need = 1, need = 1,
@ -821,6 +823,14 @@ function Builder:placePiston(b)
return return
end end
if self.wrenchSucks then
turtle.turnRight()
turtle.forward()
turtle.turnLeft()
turtle.forward()
turtle.turnLeft()
end
local success = self:wrenchBlock('forward', 'down', pistonFacings) --wrench piston to point downwards local success = self:wrenchBlock('forward', 'down', pistonFacings) --wrench piston to point downwards
rs.setOutput('front', true) rs.setOutput('front', true)
@ -830,6 +840,11 @@ function Builder:placePiston(b)
turtle.select(ps.index) turtle.select(ps.index)
turtle.dig() turtle.dig()
if not success and not self.wrenchSucks then
self.wrenchSucks = true
success = self:placePiston(b)
end
return success return success
end end
@ -2029,12 +2044,9 @@ UI:setPages({
UI:setPage('start') UI:setPage('start')
turtle.run(function() local s, m = turtle.run(function()
turtle.setPolicy(turtle.policies.digAttack) turtle.setPolicy(turtle.policies.digAttack)
turtle.setPoint({ x = -1, z = -1, y = 0, heading = 0 }) turtle.setPoint({ x = -1, z = -1, y = 0, heading = 0 })
turtle.getState().coordSystem = 'relative'
turtle.saveLocation('supplies') turtle.saveLocation('supplies')
Event.pullEvents() UI:pullEvents()
end) end)
UI.term:reset()

View File

@ -5,16 +5,18 @@ local ChestProvider = require('chestProvider18')
local RefinedProvider = require('refinedProvider') local RefinedProvider = require('refinedProvider')
local itemDB = require('itemDB') local itemDB = require('itemDB')
local Terminal = require('terminal') local Terminal = require('terminal')
local Peripheral = require('peripheral')
multishell.setTitle(multishell.getCurrent(), 'Resource Manager')
-- 3 wide monitor (any side of turtle) -- 3 wide monitor (any side of turtle)
-- Config location is /sys/config/chestManager -- Config location is /sys/config/resourceManager
-- adjust directions in that file if needed -- adjust directions in that file if needed
local config = { local config = {
trashDirection = 'up', -- trash /chest in relation to interface trashDirection = 'up', -- trash /chest in relation to chest
turtleDirection = 'down', -- turtle in relation to interface turtleDirection = 'down', -- turtle in relation to chest
noCraftingStorage = 'false' -- no ME crafting (or ability to tell if powered - use with caution)
} }
Config.load('resourceManager', config) Config.load('resourceManager', config)
@ -26,14 +28,34 @@ if not controller:isValid() then
end end
local chestProvider = ChestProvider({ direction = 'west', wrapSide = 'back' }) local chestProvider = ChestProvider({ direction = 'west', wrapSide = 'back' })
local turtleChestProvider = ChestProvider({ direction = 'up', wrapSide = 'bottom' })
local RESOURCE_FILE = 'usr/etc/resources.db'
local RECIPES_FILE = 'usr/etc/recipes.db'
local jobListGrid local jobListGrid
local craftingPaused = false local craftingPaused = false
local recipes = Util.readTable('recipes') or { } local recipes = Util.readTable(RECIPES_FILE) or { }
local resources = Util.readTable(RESOURCE_FILE) or { }
multishell.setTitle(multishell.getCurrent(), 'Resource Manager') for _,r in pairs(resources) do
r.maxDamage = nil
r.displayName = nil
r.count = nil
r.lname = nil
r.has_recipe = nil
function getItem(items, inItem, ignoreDamage) 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 for _,item in pairs(items) do
if item.name == inItem.name then if item.name == inItem.name then
if ignoreDamage then if ignoreDamage then
@ -61,7 +83,7 @@ local function getItemDetails(items, item)
cItem = itemDB:get(itemDB:makeKey(item)) cItem = itemDB:get(itemDB:makeKey(item))
if cItem then if cItem then
return { count = 0, maxCount = cItem.maxCount } return { count = 0, maxCount = cItem.maxCount }
enditemDB:makeKey end
return { count = 0, maxCount = 64 } return { count = 0, maxCount = 64 }
end end
@ -69,7 +91,7 @@ local function uniqueKey(item)
return table.concat({ item.name, item.damage, item.nbtHash }, ':') return table.concat({ item.name, item.damage, item.nbtHash }, ':')
end end
function getName(item) local function getName(item)
local detail = itemDB:get(itemDB:makeKey(item)) local detail = itemDB:get(itemDB:makeKey(item))
if detail then if detail then
return detail.displayName return detail.displayName
@ -77,60 +99,51 @@ function getName(item)
return item.name .. ':' .. item.damage return item.name .. ':' .. item.damage
end end
function mergeResources(t) local function mergeResources(t)
local resources = Util.readTable('resource.limits') or { }
for _,v in pairs(resources) do for _,v in pairs(resources) do
v.low = tonumber(v.low) -- backwards compatibility
local item = getItem(t, v) local item = getItem(t, v)
if item then if item then
item.low = v.low Util.merge(item, v)
item.limit = v.limit
item.auto = v.auto
item.ignoreDamage = v.ignoreDamage
item.rsControl = v.rsControl
item.rsDevice = v.rsDevice
item.rsSide = v.rsSide
else else
v.count = 0 item = Util.shallowCopy(v)
table.insert(t, v) item.count = 0
table.insert(t, item)
end end
end end
for _,v in pairs(recipes) do for _,v in pairs(recipes) do
local item = getItem(t, v) local item = getItem(t, v)
if item then if not item then
item.has_recipe = true
else
item = Util.shallowCopy(v) item = Util.shallowCopy(v)
item.displayName = getName(item)
item.count = 0 item.count = 0
item.has_recipe = true
table.insert(t, item) table.insert(t, item)
end end
item.has_recipe = true
end end
for _,v in pairs(t) do for _,v in pairs(t) do
if not v.displayName then
v.displayName = getName(v)
end
v.lname = v.displayName:lower() v.lname = v.displayName:lower()
end end
end end
function filterItems(t, filter) local function filterItems(t, filter)
local r = {}
if filter then if filter then
local r = {}
filter = filter:lower() filter = filter:lower()
for k,v in pairs(t) do for k,v in pairs(t) do
if string.find(v.lname, filter) then if string.find(v.lname, filter) then
table.insert(r, v) table.insert(r, v)
end end
end end
else return r
return t
end end
return r return t
end end
function sumItems3(ingredients, items, summedItems, count) local function sumItems3(ingredients, items, summedItems, count)
local canCraft = 0 local canCraft = 0
for _,item in pairs(ingredients) do for _,item in pairs(ingredients) do
@ -179,7 +192,7 @@ local function sumItems2(ingredients, items, summedItems, count)
return canCraft return canCraft
end end
function sumItems(items) local function sumItems(items)
local t = {} local t = {}
for _,item in pairs(items) do for _,item in pairs(items) do
@ -197,7 +210,7 @@ function sumItems(items)
return t return t
end end
function isGridClear() local function isGridClear()
for i = 1, 16 do for i = 1, 16 do
if turtle.getItemCount(i) ~= 0 then if turtle.getItemCount(i) ~= 0 then
return false return false
@ -219,22 +232,11 @@ local function clearGrid()
return true return true
end end
function turtleCraft(recipe, originalItem, qty) local function turtleCraft(recipe, originalItem, qty)
for k,v in pairs(recipe.ingredients) do for k,v in pairs(recipe.ingredients) do
-- ugh chestProvider:provide({ id = v.name, dmg = v.damage, nbt_hash = v.nbtHash }, v.count * qty, k)
local dmg = v.damage
--FIX - LOOKUP IN ITEMS
if v.max_dmg and v.max_dmg > 0 then
local item = ME.getItemDetail({ id = v.id, nbt_hash = v.nbt_hash }, false)
if item then
dmg = item.dmg
end
end
chestProvider:provide({ id = v.name, dmg = dmg, nbt_hash = v.nbtHash }, v.count * qty, k)
if turtle.getItemCount(k) ~= v.count * qty then if turtle.getItemCount(k) ~= v.count * qty then
clearGrid() clearGrid()
originalItem.status = v.name .. ' (extract failed)' originalItem.status = v.name .. ' (extract failed)'
@ -256,7 +258,7 @@ function turtleCraft(recipe, originalItem, qty)
return true return true
end end
function addCraftingRequest(item, craftList, count) local function addCraftingRequest(item, craftList, count)
local key = uniqueKey(item) local key = uniqueKey(item)
local request = craftList[key] local request = craftList[key]
if not craftList[key] then if not craftList[key] then
@ -267,9 +269,18 @@ function addCraftingRequest(item, craftList, count)
request.count = request.count + count request.count = request.count + count
end end
function craftRecipe(recipe, items, originalItem, count) local function craftRecipe(recipe, items, originalItem, count)
local maxCount = 64 local maxCount = recipe.maxCount
if not maxCount then -- temporary
local cItem = itemDB:get(itemDB:makeKey(recipe))
if cItem then
maxCount = cItem.maxCount
else
maxCount = 1
end
end
local summedItems = sumItems(recipe.ingredients) local summedItems = sumItems(recipe.ingredients)
for key,ingredient in pairs(summedItems) do for key,ingredient in pairs(summedItems) do
@ -293,7 +304,7 @@ function craftRecipe(recipe, items, originalItem, count)
return true return true
end end
function craftItem(recipe, items, originalItem, craftList, count) local function craftItem(recipe, items, originalItem, craftList, count)
if craftingPaused or not device.workbench or not isGridClear() then if craftingPaused or not device.workbench or not isGridClear() then
return return
@ -305,12 +316,11 @@ function craftItem(recipe, items, originalItem, craftList, count)
if toCraft > 0 then if toCraft > 0 then
craftRecipe(recipe, items, originalItem, toCraft) craftRecipe(recipe, items, originalItem, toCraft)
items = chestProvider:listItems()
end end
count = count - toCraft count = count - toCraft
items = chestProvider:listItems()
local summedItems = { } local summedItems = { }
sumItems3(recipe.ingredients, items, summedItems, count) sumItems3(recipe.ingredients, items, summedItems, count)
@ -321,7 +331,7 @@ function craftItem(recipe, items, originalItem, craftList, count)
end end
end end
function craftItems(craftList, allItems) local function craftItems(craftList, allItems)
for _,key in pairs(Util.keys(craftList)) do for _,key in pairs(Util.keys(craftList)) do
local item = craftList[key] local item = craftList[key]
@ -336,25 +346,29 @@ function craftItems(craftList, allItems)
for key,item in pairs(craftList) do for key,item in pairs(craftList) do
if controller and not recipes[key] then if not recipes[key] then
if controller:isCrafting(item) then if not controller then
item.status = '(crafting)' item.status = '(no recipe)'
else else
if controller:isCrafting(item) then
item.status = '(crafting)'
else
local count = item.count local count = item.count
while count >= 1 do -- try to request smaller quantities until successful while count >= 1 do -- try to request smaller quantities until successful
local s, m = pcall(function() local s, m = pcall(function()
item.status = '(no recipe)' item.status = '(no recipe)'
if not controller:craft(item, count) then if not controller:craft(item, count) then
item.status = '(missing ingredients)' item.status = '(missing ingredients)'
error('failed') error('failed')
end
item.status = '(crafting)'
end)
if s then
break -- successfully requested crafting
end end
item.status = '(crafting)' count = math.floor(count / 2)
end)
if s then
break -- successfully requested crafting
end end
count = math.floor(count / 2)
end end
end end
end end
@ -363,11 +377,11 @@ end
local function jobMonitor(jobList) local function jobMonitor(jobList)
local mon local mon = Peripheral.getByType('monitor')
if device.monitor then if mon then
mon = UI.Device({ mon = UI.Device({
deviceType = 'monitor', device = mon,
textScale = .5, textScale = .5,
}) })
else else
@ -387,11 +401,10 @@ local function jobMonitor(jobList)
}) })
end end
function getAutocraftItems() local function getAutocraftItems()
local t = Util.readTable('resource.limits') or { }
local craftList = { } local craftList = { }
for _,res in pairs(t) do for _,res in pairs(resources) do
if res.auto then if res.auto then
res.count = 4 -- this could be higher to increase autocrafting speed res.count = 4 -- this could be higher to increase autocrafting speed
@ -426,19 +439,18 @@ local function getItemWithQty(items, res, ignoreDamage)
return item return item
end end
function watchResources(items) local function watchResources(items)
local craftList = { } local craftList = { }
local t = Util.readTable('resource.limits') or { } for k, res in pairs(resources) do
for k, res in pairs(t) do
local item = getItemWithQty(items, res, res.ignoreDamage) local item = getItemWithQty(items, res, res.ignoreDamage)
if not item then if not item then
item = { item = {
damage = res.damage, damage = res.damage,
nbtHash = res.nbtHash, nbtHash = res.nbtHash,
name = res.name, name = res.name,
displayName = res.displayName, displayName = getName(res),
count = 0 count = 0
} }
end end
@ -472,7 +484,7 @@ function watchResources(items)
return craftList return craftList
end end
itemPage = UI.Page { local itemPage = UI.Page {
backgroundColor = colors.lightGray, backgroundColor = colors.lightGray,
titleBar = UI.TitleBar { titleBar = UI.TitleBar {
title = 'Limit Resource', title = 'Limit Resource',
@ -481,10 +493,10 @@ itemPage = UI.Page {
backgroundColor = colors.green backgroundColor = colors.green
}, },
displayName = UI.Window { displayName = UI.Window {
x = 5, y = 2, width = UI.term.width - 10, height = 3, x = 2, y = 2, width = UI.term.width - 4, height = 3,
}, },
form = UI.Form { form = UI.Form {
x = 4, y = 4, height = 8, rex = -4, x = 4, y = 5, height = 8, rex = -4,
[1] = UI.TextEntry { [1] = UI.TextEntry {
width = 7, width = 7,
backgroundColor = colors.gray, backgroundColor = colors.gray,
@ -555,7 +567,7 @@ function itemPage.displayName:draw()
local item = self.parent.item local item = self.parent.item
local str = string.format('Name: %s\nDamage: %d', item.displayName, item.damage) local str = string.format('Name: %s\nDamage: %d', item.displayName, item.damage)
if item.nbtHash then if item.nbtHash then
str = str .. string.format('\nNBT: %s\n', item.nbtHash) str = str .. string.format('\n%s', item.nbtHash)
end end
self:setCursorPos(1, 1) self:setCursorPos(1, 1)
self:print(str) self:print(str)
@ -593,9 +605,8 @@ function itemPage:eventHandler(event)
elseif event.type == 'form_complete' then elseif event.type == 'form_complete' then
local values = self.form.values local values = self.form.values
local t = Util.readTable('resource.limits') or { } local keys = { 'name', 'auto', 'low', 'limit', 'damage',
local keys = { 'name', 'displayName', 'auto', 'low', 'limit', 'damage', 'nbtHash', 'ignoreDamage',
'maxDamage', 'nbtHash', 'ignoreDamage',
'rsControl', 'rsDevice', 'rsSide', } 'rsControl', 'rsDevice', 'rsSide', }
local filtered = { } local filtered = { }
@ -605,16 +616,26 @@ function itemPage:eventHandler(event)
filtered.low = tonumber(filtered.low) filtered.low = tonumber(filtered.low)
filtered.limit = tonumber(filtered.limit) filtered.limit = tonumber(filtered.limit)
filtered.ignoreDamage = filtered.ignoreDamage == true --filtered.ignoreDamage = filtered.ignoreDamage == true
filtered.auto = filtered.auto == true --filtered.auto = filtered.auto == true
filtered.rsControl = filtered.rsControl == true --filtered.rsControl = filtered.rsControl == true
if filtered.ignoreDamage then if filtered.auto ~= true then
filtered.auto = nil
end
if filtered.rsControl ~= true then
filtered.rsControl = nil
filtered.rsSide = nil
filtered.rsDevice = nil
end
if values.ignoreDamage == true then
filtered.damage = 0 filtered.damage = 0
end end
t[uniqueKey(filtered)] = filtered resources[uniqueKey(filtered)] = filtered
Util.writeTable('resource.limits', t) Util.writeTable(RESOURCE_FILE, resources)
UI:setPreviousPage() UI:setPreviousPage()
@ -624,11 +645,12 @@ function itemPage:eventHandler(event)
return true return true
end end
listingPage = UI.Page { local listingPage = UI.Page {
menuBar = UI.MenuBar { menuBar = UI.MenuBar {
buttons = { buttons = {
{ text = 'Learn', event = 'learn' }, { text = 'Learn', event = 'learn' },
{ text = 'Forget', event = 'forget' }, { text = 'Forget', event = 'forget' },
{ text = 'Craft', event = 'craft' },
}, },
}, },
grid = UI.Grid { grid = UI.Grid {
@ -720,6 +742,9 @@ function listingPage:eventHandler(event)
self.statusBar.filter:focus() self.statusBar.filter:focus()
elseif event.type == 'learn' then elseif event.type == 'learn' then
UI:setPage('learn')
elseif event.type == 'craft' then
UI:setPage('craft') UI:setPage('craft')
elseif event.type == 'forget' then elseif event.type == 'forget' then
@ -729,16 +754,12 @@ function listingPage:eventHandler(event)
if recipes[key] then if recipes[key] then
recipes[key] = nil recipes[key] = nil
Util.writeTable('recipes', recipes) Util.writeTable(RECIPES_FILE, recipes)
end end
local resources = Util.readTable('resource.limits') or { } if resources[key] then
for k,v in pairs(resources) do resources[key] = nil
if v.name == item.name and v.damage == item.damage then Util.writeTable(RESOURCE_FILE, resources)
resources[k] = nil
Util.writeTable('resource.limits', resources)
break
end
end end
self.statusBar:timedStatus('Forgot: ' .. item.name, 3) self.statusBar:timedStatus('Forgot: ' .. item.name, 3)
@ -779,7 +800,7 @@ function listingPage:applyFilter()
end end
-- without duck antenna -- without duck antenna
local function getTurtleInventory() local function getTurtleInventoryOld()
local inventory = { } local inventory = { }
for i = 1,16 do for i = 1,16 do
if turtle.getItemCount(i) > 0 then if turtle.getItemCount(i) > 0 then
@ -795,6 +816,20 @@ local function getTurtleInventory()
return inventory return inventory
end end
local function getTurtleInventory()
local inventory = { }
for i = 1,16 do
local qty = turtle.getItemCount(i)
if qty > 0 then
turtleChestProvider:insert(i, qty)
local items = turtleChestProvider:listItems()
_, inventory[i] = next(items)
turtleChestProvider:extract(1, qty, i)
end
end
return inventory
end
local function filter(t, filter) local function filter(t, filter)
local keys = Util.keys(t) local keys = Util.keys(t)
for _,key in pairs(keys) do for _,key in pairs(keys) do
@ -817,10 +852,10 @@ local function learnRecipe(page)
clearGrid() clearGrid()
filter(recipe, { 'name', 'damage', 'nbtHash', 'count' }) filter(recipe, { 'name', 'damage', 'nbtHash', 'count', 'maxCount' })
for _,ingredient in pairs(ingredients) do for _,ingredient in pairs(ingredients) do
filter(ingredient, { 'name', 'damage', 'nbtHash', 'count' }) filter(ingredient, { 'name', 'damage', 'nbtHash', 'count', 'maxCount' })
--if ingredient.max_dmg > 0 then -- let's try this... --if ingredient.max_dmg > 0 then -- let's try this...
-- ingredient.dmg = 0 -- ingredient.dmg = 0
--end --end
@ -829,7 +864,7 @@ local function learnRecipe(page)
recipes[key] = recipe recipes[key] = recipe
Util.writeTable('recipes', recipes) Util.writeTable(RECIPES_FILE, recipes)
local displayName = getName(recipe) local displayName = getName(recipe)
@ -849,13 +884,10 @@ local function learnRecipe(page)
end end
end end
craftPage = UI.Dialog { local learnPage = UI.Dialog {
height = 7, width = UI.term.width - 6, height = 7, width = UI.term.width - 6,
backgroundColor = colors.lightGray, backgroundColor = colors.lightGray,
titleBar = UI.TitleBar { title = 'Learn Recipe',
title = 'Learn Recipe',
previousPage = true,
},
idField = UI.Text { idField = UI.Text {
x = 5, x = 5,
y = 3, y = 3,
@ -875,6 +907,61 @@ craftPage = UI.Dialog {
} }
} }
function learnPage:enable()
craftingPaused = true
self:focusFirst()
UI.Dialog.enable(self)
end
function learnPage:disable()
craftingPaused = false
UI.Dialog.disable(self)
end
function learnPage:eventHandler(event)
if event.type == 'cancel' then
UI:setPreviousPage()
elseif event.type == 'accept' then
if learnRecipe(self) then
UI:setPreviousPage()
end
else
return UI.Dialog.eventHandler(self, event)
end
return true
end
local craftPage = UI.Dialog {
height = 6, width = UI.term.width - 10,
backgroundColor = colors.lightGray,
title = 'Enter amount to craft',
idField = UI.TextEntry {
x = 15,
y = 3,
width = 10,
limit = 6,
value = '1',
backgroundColor = colors.black,
backgroundFocusColor = colors.black,
},
accept = UI.Button {
rx = -7, ry = -1,
backgroundColor = colors.green,
text = '+', event = 'accept',
},
cancel = UI.Button {
rx = -3, ry = -1,
backgroundColor = colors.red,
backgroundFocusColor = colors.red,
text = '\215', event = 'cancel'
},
}
function craftPage:draw()
UI.Dialog.draw(self)
self:write(6, 3, 'Quantity')
end
function craftPage:enable() function craftPage:enable()
craftingPaused = true craftingPaused = true
self:focusFirst() self:focusFirst()
@ -890,9 +977,7 @@ function craftPage:eventHandler(event)
if event.type == 'cancel' then if event.type == 'cancel' then
UI:setPreviousPage() UI:setPreviousPage()
elseif event.type == 'accept' then elseif event.type == 'accept' then
if learnRecipe(self) then
UI:setPreviousPage()
end
else else
return UI.Dialog.eventHandler(self, event) return UI.Dialog.eventHandler(self, event)
end end
@ -902,6 +987,7 @@ end
UI:setPages({ UI:setPages({
listing = listingPage, listing = listingPage,
item = itemPage, item = itemPage,
learn = learnPage,
craft = craftPage, craft = craftPage,
}) })
@ -913,15 +999,12 @@ jobMonitor()
jobListGrid:draw() jobListGrid:draw()
jobListGrid:sync() jobListGrid:sync()
function craftingThread() local function craftingThread()
while true do while true do
os.sleep(5) os.sleep(5)
if not craftingPaused then if not craftingPaused then
local items = chestProvider:listItems() local items = chestProvider:listItems()
if Util.size(items) == 0 then if Util.size(items) == 0 then
jobListGrid.parent:clear() jobListGrid.parent:clear()
jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'No items in system') jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'No items in system')
@ -942,8 +1025,6 @@ function craftingThread()
end end
end end
end end
--craftingThread()
UI:pullEvents(craftingThread)
UI.term:reset() UI:pullEvents(craftingThread)
jobListGrid.parent:reset() jobListGrid.parent:reset()

View File

@ -61,40 +61,37 @@ function getClient(id)
return ids[id] return ids[id]
end end
local function logWriter() Event.on('logMessage', function()
while true do local t = { }
os.pullEvent('logMessage') while #messages > 0 do
local t = { } local msg = messages[1]
while #messages > 0 do table.remove(messages, 1)
local msg = messages[1] local client = getClient(msg.id)
table.remove(messages, 1) client.scrollingText:appendLine(string.format('%d %s', math.floor(os.clock()), msg.text))
local client = getClient(msg.id) t[msg.id] = client
client.scrollingText:appendLine(string.format('%d %s', math.floor(os.clock()), msg.text))
t[msg.id] = client
end
for _,client in pairs(t) do
client.scrollingText:draw()
end
terminal:sync()
end end
end for _,client in pairs(t) do
client.scrollingText:draw()
end
terminal:sync()
end)
Message.addHandler('log', function(h, id, msg) Message.addHandler('log', function(h, id, msg)
table.insert(messages, { id = id, text = msg.contents }) table.insert(messages, { id = id, text = msg.contents })
os.queueEvent('logMessage') os.queueEvent('logMessage')
end) end)
Event.addHandler('monitor_touch', function() Event.on('monitor_touch', function()
terminal:reset() terminal:reset()
ids = { } ids = { }
end) end)
Event.addHandler('mouse_click', function() Event.on('mouse_click', function()
terminal:reset() terminal:reset()
ids = { } ids = { }
end) end)
Event.addHandler('char', function() Event.on('char', function()
Event.exitPullEvents() Event.exitPullEvents()
end) end)

View File

@ -2,7 +2,7 @@ require = requireInjector(getfenv(1))
local Socket = require('socket') local Socket = require('socket')
local Terminal = require('terminal') local Terminal = require('terminal')
local Logger = require('logger') local Logger = require('logger')
local process = require('process') local Event = require('event')
Logger.setScreenLogging() Logger.setScreenLogging()
@ -31,7 +31,12 @@ local function wrapTerm(socket)
socket.term[k] = function(...) socket.term[k] = function(...)
if not socket.queue then if not socket.queue then
socket.queue = { } socket.queue = { }
os.queueEvent('mirror_flush') Event.onTimeout(0, function()
if socket.queue then
socket:write(socket.queue)
socket.queue = nil
end
end)
end end
table.insert(socket.queue, { table.insert(socket.queue, {
f = k, f = k,
@ -61,17 +66,13 @@ while true do
os.queueEvent('term_resize') os.queueEvent('term_resize')
while true do while true do
local e = process:pullEvent('mirror_flush') local e = Event.pullEvent()
if e == 'terminate' then if e == 'terminate' then
break break
end end
if not socket.connected then if not socket.connected then
break break
end end
if socket.queue then
socket:write(socket.queue)
socket.queue = nil
end
end end
for k,v in pairs(socket.oldTerm) do for k,v in pairs(socket.oldTerm) do

View File

@ -1,7 +1,7 @@
require = requireInjector(getfenv(1)) require = requireInjector(getfenv(1))
local Event = require('event')
local Socket = require('socket') local Socket = require('socket')
local Logger = require('logger') local Logger = require('logger')
local process = require('process')
Logger.setScreenLogging() Logger.setScreenLogging()
@ -20,7 +20,7 @@ while true do
print('mirror: connection from ' .. socket.dhost) print('mirror: connection from ' .. socket.dhost)
local updateThread = process:newThread('updateThread', function() Event.addRoutine(function()
while true do while true do
local data = socket:read() local data = socket:read()
if not data then if not data then
@ -33,18 +33,15 @@ while true do
end) end)
-- ensure socket is connected -- ensure socket is connected
process:newThread('pinger', function() Event.onInterval(3, function(h)
while true do if not socket:ping() then
os.sleep(3) Event.off(h)
if not socket:ping() then
break
end
end end
end) end)
while true do while true do
process:pullEvent('modem_message') Event.pullEvent()
if updateThread:isDead() then if not socket.connected then
break break
end end
end end

View File

@ -243,6 +243,159 @@ turtle.run(function()
end) end)
]] ]]
local levelScript = [[
require = requireInjector(getfenv(1))
local Point = require('point')
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)
turtle.pathfind(pt)
if not s and m then
error(m)
end
end
end)
if not s then
error(m)
end
]]
local data = Util.readTable('/usr/config/shapes') or { } local data = Util.readTable('/usr/config/shapes') or { }
local page = UI.Page { local page = UI.Page {
@ -251,6 +404,7 @@ local page = UI.Page {
startCoord = UI.Button { x = 2, y = 6, text = 'Start ', event = 'startCoord' }, startCoord = UI.Button { x = 2, y = 6, text = 'Start ', event = 'startCoord' },
endCoord = UI.Button { x = 2, y = 8, text = 'End ', event = 'endCoord' }, endCoord = UI.Button { x = 2, y = 8, text = 'End ', event = 'endCoord' },
supplies = UI.Button { x = 2, y = 10, text = 'Supplies', event = 'supplies' }, supplies = UI.Button { x = 2, y = 10, text = 'Supplies', event = 'supplies' },
first = UI.Button { x = 2, y = 11, text = 'First', event = 'firstCoord' },
cancel = UI.Button { rx = 2, ry = -2, text = 'Abort', event = 'cancel' }, cancel = UI.Button { rx = 2, ry = -2, text = 'Abort', event = 'cancel' },
begin = UI.Button { rx = -7, ry = -2, text = 'Begin', event = 'begin' }, begin = UI.Button { rx = -7, ry = -2, text = 'Begin', event = 'begin' },
accelerators = { q = 'quit' }, accelerators = { q = 'quit' },
@ -286,6 +440,7 @@ end
function page:runFunction(id, script) function page:runFunction(id, script)
Util.writeFile('script.tmp', script)
self.notification:info('Connecting') self.notification:info('Connecting')
local fn, msg = loadstring(script, 'script') local fn, msg = loadstring(script, 'script')
if not fn then if not fn then
@ -299,7 +454,6 @@ function page:runFunction(id, script)
self.notification:error('Unable to connect') self.notification:error('Unable to connect')
return return
end end
socket:write({ type = 'script', args = script }) socket:write({ type = 'script', args = script })
socket:close() socket:close()
@ -321,6 +475,13 @@ function page:eventHandler(event)
Util.writeTable('/usr/config/shapes', data) Util.writeTable('/usr/config/shapes', data)
end end
self:draw() self:draw()
elseif event.type == 'firstCoord' then
data.firstPt = self:getPoint()
if data.firstPt then
self.statusBar:setStatus('first point set')
Util.writeTable('/usr/config/shapes', data)
end
self:draw()
elseif event.type == 'supplies' then elseif event.type == 'supplies' then
data.suppliesPt = self:getPoint() data.suppliesPt = self:getPoint()
if data.suppliesPt then if data.suppliesPt then
@ -329,7 +490,7 @@ function page:eventHandler(event)
end end
elseif event.type == 'begin' then elseif event.type == 'begin' then
if data.startPt and data.endPt then if data.startPt and data.endPt then
local s = 'local data = ' .. textutils.serialize(data) .. script local s = 'local data = ' .. textutils.serialize(data) .. levelScript
self:runFunction(turtleId, s) self:runFunction(turtleId, s)
else else
self.notification:error('Corners not set') self.notification:error('Corners not set')

View File

@ -863,43 +863,37 @@ jobMonitor()
jobListGrid:draw() jobListGrid:draw()
jobListGrid:sync() jobListGrid:sync()
function craftingThread() Event.onInterval(5, function()
while true do if not craftingPaused then
os.sleep(5)
if not craftingPaused then local items = ME.getAvailableItems()
if Util.size(items) == 0 then
jobListGrid.parent:clear()
jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'No items in system')
jobListGrid:sync()
elseif config.noCraftingStorage ~= 'true' and #ME.getCraftingCPUs() <= 0 then -- only way to determine if AE is online
jobListGrid.parent:clear()
jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'Power failure')
jobListGrid:sync()
local items = ME.getAvailableItems() else
local itemList = watchResources(items)
if Util.size(items) == 0 then jobListGrid:setValues(itemList)
jobListGrid.parent:clear() jobListGrid:draw()
jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'No items in system') jobListGrid:sync()
jobListGrid:sync() craftItems(itemList)
jobListGrid:update()
elseif config.noCraftingStorage ~= 'true' and #ME.getCraftingCPUs() <= 0 then -- only way to determine if AE is online jobListGrid:draw()
jobListGrid.parent:clear() jobListGrid:sync()
jobListGrid.parent:centeredWrite(math.ceil(jobListGrid.parent.height/2), 'Power failure')
jobListGrid:sync()
else itemList = getAutocraftItems(items) -- autocrafted items don't show on job monitor
local itemList = watchResources(items) craftItems(itemList)
jobListGrid:setValues(itemList)
jobListGrid:draw()
jobListGrid:sync()
craftItems(itemList)
jobListGrid:update()
jobListGrid:draw()
jobListGrid:sync()
itemList = getAutocraftItems(items) -- autocrafted items don't show on job monitor
craftItems(itemList)
end
end end
end end
end end)
Event.pullEvents(craftingThread) UI:pullEvents()
UI.term:reset()
jobListGrid.parent:reset() jobListGrid.parent:reset()

View File

@ -429,7 +429,6 @@ end
turtle.run(function() turtle.run(function()
turtle.setPoint({ x = -1, z = -2, y = -1, heading = 1 }) turtle.setPoint({ x = -1, z = -2, y = -1, heading = 1 })
turtle.getState().coordSystem = 'relative'
turtle.saveLocation('supplies') turtle.saveLocation('supplies')

View File

@ -1,5 +1,5 @@
require = requireInjector(getfenv(1)) require = requireInjector(getfenv(1))
local process = require('process') local Event = require('event')
local Socket = require('socket') local Socket = require('socket')
local Terminal = require('terminal') local Terminal = require('terminal')
@ -36,7 +36,7 @@ socket:write({
isColor = ct.isColor(), isColor = ct.isColor(),
}) })
process:newThread('telnet_read', function() Event.addRoutine(function()
while true do while true do
local data = socket:read() local data = socket:read()
if not data then if not data then
@ -57,7 +57,7 @@ local filter = Util.transpose({
}) })
while true do while true do
local e = { process:pullEvent() } local e = Event.pullEvent()
local event = e[1] local event = e[1]
if not socket.connected then if not socket.connected then

View File

@ -1,5 +1,5 @@
require = requireInjector(getfenv(1)) require = requireInjector(getfenv(1))
local process = require('process') local Event = require('event')
local Socket = require('socket') local Socket = require('socket')
local Terminal = require('terminal') local Terminal = require('terminal')
@ -39,7 +39,7 @@ if not ct.isColor() then
Terminal.toGrayscale(ct) Terminal.toGrayscale(ct)
end end
process:newThread('vnc_read', function() Event.addRoutine(function()
while true do while true do
local data = socket:read() local data = socket:read()
if not data then if not data then
@ -60,7 +60,7 @@ local filter = Util.transpose({
}) })
while true do while true do
local e = { process:pullEvent() } local e = Event.pullEvent()
local event = e[1] local event = e[1]
if not socket.connected then if not socket.connected then

83
sys/etc/scripts/level Normal file
View File

@ -0,0 +1,83 @@
require = requireInjector(getfenv(1))
local Point = require('point')
local checkedNodes = { }
local nodes = { }
local box = { x = 65, ex = 69, y = 65, ey = 70, z = -23, ez = -19 }
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(facing)
local direction = facing
if direction == 'forward' then
direction = turtle.getHeadingInfo(turtle.point.heading).direction
end
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
if turtle.getAction(facing).dig() then
addNode(node)
end
end
end
local function level()
repeat
local node = { x = turtle.point.x, y = turtle.point.y, z = turtle.point.z }
local key = toKey(node)
checkedNodes[key] = true
nodes[key] = nil
dig('down')
dig('up')
dig('forward')
print(string.format('%d nodes remaining', Util.size(nodes)))
if Util.size(nodes) == 0 then
break
end
local node = Point.closest(turtle.point, nodes)
if not turtle.gotoPoint(node) then
break
end
until turtle.abort
end
local pt = Util.shallowCopy(turtle.point)
turtle.setPolicy(turtle.policies.none)
if turtle.pathfind({ x = 65, y = 70, z = -23 }) then
--turtle.reset()
turtle.setPolicy(turtle.policies.digOnly)
level()
end
turtle.pathfind(pt)
--local s, m = turtle.run(level)

View File

@ -7,7 +7,6 @@ local function summon(id)
turtle.status = 'GPSing' turtle.status = 'GPSing'
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 }) turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 })
turtle.getState().coordSystem = 'relative'
local pts = { local pts = {
[ 1 ] = { x = 0, z = 0, y = 0 }, [ 1 ] = { x = 0, z = 0, y = 0 },

View File

@ -6,15 +6,14 @@ require = requireInjector(getfenv(1))
local GPS = require('gps') local GPS = require('gps')
function turtle.enableGPS(timeout) function turtle.enableGPS(timeout)
if turtle.getState().coordSystem == 'GPS' then if turtle.point.gps == 'GPS' then
return turtle.point return turtle.point
end end
local pt = GPS.getPointAndHeading(timeout) local pt = GPS.getPointAndHeading(timeout)
if pt then if pt then
turtle.setPoint(pt) turtle.setPoint(pt, true)
turtle.getState().coordSystem = 'GPS' return turtle.point
return true
end end
end end

View File

@ -7,30 +7,40 @@ local function noop() end
turtle.point = { x = 0, y = 0, z = 0, heading = 0 } turtle.point = { x = 0, y = 0, z = 0, heading = 0 }
turtle.status = 'idle' turtle.status = 'idle'
turtle.abort = false turtle.abort = false
local state = { }
function turtle.getPoint() function turtle.getPoint() return turtle.point end
return turtle.point function turtle.getState() return state end
local function _defaultMove(action)
while not action.move() do
if not state.digPolicy(action) and not state.attackPolicy(action) then
return false
end
end
return true
end end
local state = { function turtle.setPoint(pt, isGPS)
moveAttack = noop,
moveDig = noop,
moveCallback = noop,
locations = {},
coordSystem = 'relative', -- type of coordinate system being used
}
function turtle.getState()
return state
end
function turtle.setPoint(pt)
turtle.point.x = pt.x turtle.point.x = pt.x
turtle.point.y = pt.y turtle.point.y = pt.y
turtle.point.z = pt.z turtle.point.z = pt.z
if pt.heading then if pt.heading then
turtle.point.heading = pt.heading turtle.point.heading = pt.heading
end end
turtle.point.gps = isGPS
return true
end
function turtle.resetState()
--turtle.abort = false -- should be part of state
--turtle.status = 'idle' -- should be part of state
state.attackPolicy = noop
state.digPolicy = noop
state.movePolicy = _defaultMove
state.moveCallback = noop
state.locations = { }
return true return true
end end
@ -39,27 +49,16 @@ function turtle.reset()
turtle.point.y = 0 turtle.point.y = 0
turtle.point.z = 0 turtle.point.z = 0
turtle.point.heading = 0 turtle.point.heading = 0
turtle.point.gps = false
turtle.abort = false -- should be part of state turtle.abort = false -- should be part of state
--turtle.status = 'idle' -- should be part of state --turtle.status = 'idle' -- should be part of state
state.moveAttack = noop
state.moveDig = noop turtle.resetState()
state.moveCallback = noop
state.locations = {}
state.coordSystem = 'relative'
return true return true
end end
function turtle.resetState() turtle.reset()
--turtle.abort = false -- should be part of state
--turtle.status = 'idle' -- should be part of state
state.moveAttack = noop
state.moveDig = noop
state.moveCallback = noop
state.locations = {}
return true
end
local actions = { local actions = {
up = { up = {
@ -116,12 +115,12 @@ end
-- [[ Heading data ]] -- -- [[ Heading data ]] --
local headings = { local headings = {
[ 0 ] = { xd = 1, zd = 0, yd = 0, heading = 0, direction = 'east' }, [ 0 ] = { xd = 1, zd = 0, yd = 0, heading = 0, direction = 'east' },
[ 1 ] = { xd = 0, zd = 1, yd = 0, heading = 1, direction = 'south' }, [ 1 ] = { xd = 0, zd = 1, yd = 0, heading = 1, direction = 'south' },
[ 2 ] = { xd = -1, zd = 0, yd = 0, heading = 2, direction = 'west' }, [ 2 ] = { xd = -1, zd = 0, yd = 0, heading = 2, direction = 'west' },
[ 3 ] = { xd = 0, zd = -1, yd = 0, heading = 3, direction = 'north' }, [ 3 ] = { xd = 0, zd = -1, yd = 0, heading = 3, direction = 'north' },
[ 4 ] = { xd = 0, zd = 0, yd = 1, heading = 4, direction = 'up' }, [ 4 ] = { xd = 0, zd = 0, yd = 1, heading = 4, direction = 'up' },
[ 5 ] = { xd = 0, zd = 0, yd = -1, heading = 5, direction = 'down' } [ 5 ] = { xd = 0, zd = 0, yd = -1, heading = 5, direction = 'down' }
} }
local namedHeadings = { local namedHeadings = {
@ -133,9 +132,7 @@ local namedHeadings = {
down = headings[5] down = headings[5]
} }
function turtle.getHeadings() function turtle.getHeadings() return headings end
return headings
end
function turtle.getHeadingInfo(heading) function turtle.getHeadingInfo(heading)
if heading and type(heading) == 'string' then if heading and type(heading) == 'string' then
@ -181,8 +178,8 @@ local function _place(action, indexOrId)
if result[1] then if result[1] then
return true return true
end end
if not state.moveDig(action) then if not state.digPolicy(action) then
state.moveAttack(action) state.attackPolicy(action)
end end
return unpack(result) return unpack(result)
end) end)
@ -267,48 +264,66 @@ turtle.digPolicies = {
end end
} }
turtle.policies = { turtle.movePolicies = {
none = { dig = turtle.digPolicies.none, attack = turtle.attackPolicies.none }, none = noop,
digOnly = { dig = turtle.digPolicies.dig, attack = turtle.attackPolicies.none }, default = _defaultMove,
attackOnly = { dig = turtle.digPolicies.none, attack = turtle.attackPolicies.attack }, assured = function(action)
digAttack = { dig = turtle.digPolicies.dig, attack = turtle.attackPolicies.attack }, if not _defaultMove(action) then
turtleSafe = { dig = turtle.digPolicies.turtleSafe, attack = turtle.attackPolicies.attack }, if action.side == 'back' then
return false
end
local oldStatus = turtle.status
print('stuck')
turtle.status = 'stuck'
repeat
os.sleep(1)
until _defaultMove(action)
turtle.status = oldStatus
end
return true
end,
} }
function turtle.setPolicy(policy) turtle.policies = {
if type(policy) == 'string' then none = { dig = turtle.digPolicies.none, attack = turtle.attackPolicies.none },
policy = turtle.policies[policy] digOnly = { dig = turtle.digPolicies.dig, attack = turtle.attackPolicies.none },
attackOnly = { dig = turtle.digPolicies.none, attack = turtle.attackPolicies.attack },
digAttack = { dig = turtle.digPolicies.dig, attack = turtle.attackPolicies.attack },
turtleSafe = { dig = turtle.digPolicies.turtleSafe, attack = turtle.attackPolicies.attack },
attack = { attack = turtle.attackPolicies.attack },
defaultMove = { move = turtle.movePolicies.default },
assuredMove = { move = turtle.movePolicies.assured },
}
function turtle.setPolicy(...)
local args = { ... }
for _, policy in pairs(args) do
if type(policy) == 'string' then
policy = turtle.policies[policy]
end
if not policy then
error('Invalid policy')
-- return false, 'Invalid policy'
end
if policy.dig then
state.digPolicy = policy.dig
end
if policy.attack then
state.attackPolicy = policy.attack
end
if policy.move then
state.movePolicy = policy.move
end
end end
if not policy then
return false, 'Invalid policy'
end
state.moveDig = policy.dig
state.moveAttack = policy.attack
return true return true
end end
function turtle.setDigPolicy(policy) function turtle.setDigPolicy(policy) state.digPolicy = policy end
state.moveDig = policy function turtle.setAttackPolicy(policy) state.attackPolicy = policy end
end function turtle.setMoveCallback(cb) state.moveCallback = cb end
function turtle.clearMoveCallback() state.moveCallback = noop end
function turtle.setAttackPolicy(policy)
state.moveAttack = policy
end
function turtle.setMoveCallback(cb)
state.moveCallback = cb
end
function turtle.clearMoveCallback()
state.moveCallback = noop
end
local function infoMoveCallback()
local pt = turtle.point
print(string.format('x:%d y:%d z:%d heading:%d', pt.x, pt.y, pt.z, pt.heading))
end
-- TESTING
--turtle.setMoveCallback(infoMoveCallback)
-- [[ Locations ]] -- -- [[ Locations ]] --
function turtle.getLocation(name) function turtle.getLocation(name)
@ -364,6 +379,7 @@ function turtle.turnAround()
return turtle.point return turtle.point
end end
-- combine with setHeading
function turtle.setNamedHeading(headingName) function turtle.setNamedHeading(headingName)
local headingInfo = namedHeadings[headingName] local headingInfo = namedHeadings[headingName]
if headingInfo then if headingInfo then
@ -432,17 +448,8 @@ function turtle.headTowards(pt)
end end
-- [[ move ]] -- -- [[ move ]] --
local function _move(action)
while not action.move() do
if not state.moveDig(action) and not state.moveAttack(action) then
return false
end
end
return true
end
function turtle.up() function turtle.up()
if _move(actions.up) then if state.movePolicy(actions.up) then
turtle.point.y = turtle.point.y + 1 turtle.point.y = turtle.point.y + 1
state.moveCallback('up', turtle.point) state.moveCallback('up', turtle.point)
return true, turtle.point return true, turtle.point
@ -450,7 +457,7 @@ function turtle.up()
end end
function turtle.down() function turtle.down()
if _move(actions.down) then if state.movePolicy(actions.down) then
turtle.point.y = turtle.point.y - 1 turtle.point.y = turtle.point.y - 1
state.moveCallback('down', turtle.point) state.moveCallback('down', turtle.point)
return true, turtle.point return true, turtle.point
@ -458,7 +465,7 @@ function turtle.down()
end end
function turtle.forward() function turtle.forward()
if _move(actions.forward) then if state.movePolicy(actions.forward) then
turtle.point.x = turtle.point.x + headings[turtle.point.heading].xd turtle.point.x = turtle.point.x + headings[turtle.point.heading].xd
turtle.point.z = turtle.point.z + headings[turtle.point.heading].zd turtle.point.z = turtle.point.z + headings[turtle.point.heading].zd
state.moveCallback('forward', turtle.point) state.moveCallback('forward', turtle.point)
@ -467,7 +474,7 @@ function turtle.forward()
end end
function turtle.back() function turtle.back()
if _move(actions.back) then if state.movePolicy(actions.back) then
turtle.point.x = turtle.point.x - headings[turtle.point.heading].xd turtle.point.x = turtle.point.x - headings[turtle.point.heading].xd
turtle.point.z = turtle.point.z - headings[turtle.point.heading].zd turtle.point.z = turtle.point.z - headings[turtle.point.heading].zd
state.moveCallback('back', turtle.point) state.moveCallback('back', turtle.point)

View File

@ -129,7 +129,6 @@ local function sendInfo()
info.status = turtle.status info.status = turtle.status
info.point = turtle.point info.point = turtle.point
info.inventory = turtle.getInventory() info.inventory = turtle.getInventory()
info.coordSystem = turtle.getState().coordSystem
info.slotIndex = turtle.getSelectedSlot() info.slotIndex = turtle.getSelectedSlot()
end end
device.wireless_modem.transmit(999, os.getComputerID(), info) device.wireless_modem.transmit(999, os.getComputerID(), info)

View File

@ -75,9 +75,9 @@ process:newThread('vnc_server', function()
local termInfo = socket:read(5) local termInfo = socket:read(5)
if termInfo then if termInfo then
-- no new process - only 1 connection allowed -- no new process - only 1 connection allowed
-- due to term size issues -- due to term size issues
vncHost(socket, termInfo) vncHost(socket, termInfo)
else else
socket:close() socket:close()
end end

View File

@ -12,7 +12,7 @@ if not term.isColor() then
detachColor = colors.lightGray detachColor = colors.lightGray
end end
Event.addHandler('peripheral', function(event, side) Event.on('peripheral', function(event, side)
if side then if side then
local dev = Peripheral.addDevice(device, side) local dev = Peripheral.addDevice(device, side)
if dev then if dev then
@ -23,7 +23,7 @@ Event.addHandler('peripheral', function(event, side)
end end
end) end)
Event.addHandler('peripheral_detach', function(event, side) Event.on('peripheral_detach', function(event, side)
if side then if side then
local dev = Util.find(device, 'side', side) local dev = Util.find(device, 'side', side)
if dev then if dev then