mirror of
https://github.com/kepler155c/opus
synced 2025-02-03 02:49:09 +00:00
Replace process.api with Event
This commit is contained in:
parent
f8bcf90a6b
commit
be51935662
@ -2,120 +2,152 @@ local Util = require('util')
|
||||
|
||||
local Event = {
|
||||
uid = 1, -- unique id for handlers
|
||||
routines = { },
|
||||
handlers = { namedTimers = { } },
|
||||
routines = { }, -- coroutines
|
||||
types = { }, -- event handlers
|
||||
timers = { }, -- named timers
|
||||
terminate = false,
|
||||
}
|
||||
|
||||
function Event.addHandler(type, f)
|
||||
local event = Event.handlers[type]
|
||||
local Routine = { }
|
||||
|
||||
function Routine:isDead()
|
||||
if not self.co then
|
||||
return true
|
||||
end
|
||||
return coroutine.status(self.co) == 'dead'
|
||||
end
|
||||
|
||||
function Routine:terminate()
|
||||
if self.co then
|
||||
self:resume('terminate')
|
||||
end
|
||||
end
|
||||
|
||||
function Routine:resume(event, ...)
|
||||
|
||||
if not self.co then
|
||||
debug(event)
|
||||
debug(self)
|
||||
debug(getfenv(1))
|
||||
error('Cannot resume a dead routine')
|
||||
end
|
||||
|
||||
if not self.filter or self.filter == event or event == "terminate" then
|
||||
local s, m = coroutine.resume(self.co, event, ...)
|
||||
|
||||
if coroutine.status(self.co) == 'dead' then
|
||||
self.co = nil
|
||||
self.filter = nil
|
||||
Event.routines[self.uid] = nil
|
||||
else
|
||||
self.filter = m
|
||||
end
|
||||
|
||||
if not s and event ~= 'terminate' then
|
||||
debug({s, m})
|
||||
debug(self)
|
||||
debug(getfenv(1))
|
||||
error('\n' .. (m or 'Error processing event'))
|
||||
end
|
||||
|
||||
return s, m
|
||||
end
|
||||
|
||||
return true, self.filter
|
||||
end
|
||||
|
||||
local function nextUID()
|
||||
Event.uid = Event.uid + 1
|
||||
return Event.uid - 1
|
||||
end
|
||||
|
||||
function Event.on(type, fn)
|
||||
local event = Event.types[type]
|
||||
if not event then
|
||||
event = { handlers = { } }
|
||||
Event.handlers[type] = event
|
||||
event = { }
|
||||
Event.types[type] = event
|
||||
end
|
||||
|
||||
local handler = {
|
||||
uid = Event.uid,
|
||||
uid = nextUID(),
|
||||
event = type,
|
||||
f = f,
|
||||
fn = fn,
|
||||
}
|
||||
Event.uid = Event.uid + 1
|
||||
event.handlers[handler.uid] = handler
|
||||
event[handler.uid] = handler
|
||||
setmetatable(handler, { __index = Routine })
|
||||
|
||||
return handler
|
||||
end
|
||||
|
||||
function Event.removeHandler(h)
|
||||
function Event.off(h)
|
||||
if h and h.event then
|
||||
Event.handlers[h.event].handlers[h.uid] = nil
|
||||
Event.types[h.event][h.uid] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function Event.queueTimedEvent(name, timeout, event, args)
|
||||
Event.addNamedTimer(name, timeout, false,
|
||||
function()
|
||||
os.queueEvent(event, args)
|
||||
local function addTimer(interval, recurring, fn)
|
||||
|
||||
local timerId = os.startTimer(interval)
|
||||
|
||||
return Event.on('timer', function(t, id)
|
||||
if timerId == id then
|
||||
fn(t, id)
|
||||
if recurring then
|
||||
timerId = os.startTimer(interval)
|
||||
else
|
||||
Event.off(t)
|
||||
end
|
||||
)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Event.addNamedTimer(name, interval, recurring, f)
|
||||
function Event.onInterval(interval, fn)
|
||||
return addTimer(interval, true, fn)
|
||||
end
|
||||
|
||||
function Event.onTimeout(timeout, fn)
|
||||
return addTimer(timeout, false, fn)
|
||||
end
|
||||
|
||||
function Event.addNamedTimer(name, interval, recurring, fn)
|
||||
Event.cancelNamedTimer(name)
|
||||
Event.handlers.namedTimers[name] = Event.addTimer(interval, recurring, f)
|
||||
end
|
||||
|
||||
function Event.getNamedTimer(name)
|
||||
return Event.handlers.namedTimers[name]
|
||||
Event.timers[name] = addTimer(interval, recurring, fn)
|
||||
end
|
||||
|
||||
function Event.cancelNamedTimer(name)
|
||||
local timer = Event.getNamedTimer(name)
|
||||
local timer = Event.timers[name]
|
||||
if timer then
|
||||
timer.enabled = false
|
||||
Event.removeHandler(timer)
|
||||
Event.off(timer)
|
||||
end
|
||||
end
|
||||
|
||||
function Event.addTimer(interval, recurring, f)
|
||||
local timer = Event.addHandler('timer',
|
||||
function(t, id)
|
||||
if t.timerId ~= id then
|
||||
return
|
||||
end
|
||||
if t.enabled then
|
||||
t.fired = true
|
||||
t.cf(t, id)
|
||||
end
|
||||
if t.recurring then
|
||||
t.fired = false
|
||||
t.timerId = os.startTimer(t.interval)
|
||||
else
|
||||
Event.removeHandler(t)
|
||||
end
|
||||
end
|
||||
)
|
||||
timer.cf = f
|
||||
timer.interval = interval
|
||||
timer.recurring = recurring
|
||||
timer.enabled = true
|
||||
timer.timerId = os.startTimer(interval)
|
||||
|
||||
return timer
|
||||
end
|
||||
|
||||
function Event.onInterval(interval, f)
|
||||
return Event.addTimer(interval, true, f)
|
||||
end
|
||||
|
||||
function Event.onTimeout(timeout, f)
|
||||
return Event.addTimer(timeout, false, f)
|
||||
end
|
||||
|
||||
function Event.waitForEvent(event, timeout)
|
||||
local timerId = os.startTimer(timeout)
|
||||
repeat
|
||||
local e, p1, p2, p3, p4 = os.pullEvent()
|
||||
if e == event then
|
||||
return e, p1, p2, p3, p4
|
||||
local e = { os.pullEvent() }
|
||||
if e[1] == event then
|
||||
return table.unpack(e)
|
||||
end
|
||||
until e == 'timer' and p1 == timerId
|
||||
until e[1] == 'timer' and e[2] == timerId
|
||||
end
|
||||
|
||||
function Event.addRoutine(routine)
|
||||
local r = { co = coroutine.create(routine) }
|
||||
local s, m = coroutine.resume(r.co)
|
||||
if not s then
|
||||
error(m or 'Error processing routine')
|
||||
end
|
||||
Event.routines[r] = true
|
||||
r.filter = m
|
||||
function Event.addRoutine(fn)
|
||||
local r = {
|
||||
co = coroutine.create(fn),
|
||||
uid = nextUID()
|
||||
}
|
||||
setmetatable(r, { __index = Routine })
|
||||
Event.routines[r.uid] = r
|
||||
|
||||
r:resume()
|
||||
|
||||
return r
|
||||
end
|
||||
|
||||
function Event.pullEvents(...)
|
||||
|
||||
for _, r in ipairs({ ... }) do
|
||||
Event.addRoutine(r)
|
||||
for _, fn in ipairs({ ... }) do
|
||||
Event.addRoutine(fn)
|
||||
end
|
||||
|
||||
repeat
|
||||
@ -128,28 +160,43 @@ function Event.exitPullEvents()
|
||||
os.sleep(0)
|
||||
end
|
||||
|
||||
local function processHandlers(e, ...)
|
||||
|
||||
local event = Event.types[e]
|
||||
if event then
|
||||
|
||||
local keys = Util.keys(event)
|
||||
for _,key in pairs(keys) do
|
||||
|
||||
local h = event[key]
|
||||
if h and not h.co then
|
||||
-- callbacks are single threaded (only 1 co per handler)
|
||||
h.co = coroutine.create(h.fn)
|
||||
Event.routines[h.uid] = h
|
||||
h:resume(h, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function processRoutines(...)
|
||||
local keys = Util.keys(Event.routines)
|
||||
for _,key in ipairs(keys) do
|
||||
local r = Event.routines[key]
|
||||
if r then
|
||||
r:resume(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Event.pullEvent(eventType)
|
||||
|
||||
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)
|
||||
|
||||
processHandlers(table.unpack(e))
|
||||
processRoutines(table.unpack(e))
|
||||
|
||||
if Event.terminate or e[1] == 'terminate' then
|
||||
Event.terminate = false
|
||||
return { 'terminate' }
|
||||
@ -161,37 +208,4 @@ function Event.pullEvent(eventType)
|
||||
end
|
||||
end
|
||||
|
||||
function Event.processEvent(pe)
|
||||
|
||||
local e, p1, p2, p3, p4, p5 = unpack(pe)
|
||||
|
||||
local event = Event.handlers[e]
|
||||
if event then
|
||||
local keys = Util.keys(event.handlers)
|
||||
for _,key in pairs(keys) do
|
||||
local h = event.handlers[key]
|
||||
if h and not h.co then
|
||||
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
|
||||
|
||||
return e, p1, p2, p3, p4, p5
|
||||
end
|
||||
|
||||
Event.on = Event.addHandler
|
||||
Event.off = Event.removeHandler
|
||||
|
||||
return Event
|
||||
|
@ -18,7 +18,7 @@ if device and device.wireless_modem then
|
||||
Message.enable()
|
||||
end
|
||||
|
||||
Event.addHandler('device_attach', function(event, deviceName)
|
||||
Event.on('device_attach', function(event, deviceName)
|
||||
if deviceName == 'wireless_modem' then
|
||||
Message.enable()
|
||||
end
|
||||
@ -41,7 +41,7 @@ function Message.removeHandler(h)
|
||||
end
|
||||
end
|
||||
|
||||
Event.addHandler('modem_message',
|
||||
Event.on('modem_message',
|
||||
function(event, side, sendChannel, replyChannel, msg, distance)
|
||||
if msg and msg.type then -- filter out messages from other systems
|
||||
local id = replyChannel
|
||||
|
@ -66,8 +66,20 @@ function Manager:init(args)
|
||||
local shift = false
|
||||
local mouseDragged = false
|
||||
local pages = { }
|
||||
local running = false
|
||||
|
||||
Event.on('term_resize', function(h, side)
|
||||
-- single thread all input events
|
||||
local function singleThread(event, fn)
|
||||
Event.on(event, function(...)
|
||||
if not running then
|
||||
running = true
|
||||
fn(...)
|
||||
running = false
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
singleThread('term_resize', function(h, side)
|
||||
if self.currentPage then
|
||||
-- the parent doesn't have any children set...
|
||||
-- that's why we have to resize both the parent and the current page
|
||||
@ -81,7 +93,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('mouse_scroll', function(h, direction, x, y)
|
||||
singleThread('mouse_scroll', function(h, direction, x, y)
|
||||
if self.target then
|
||||
local event = self:pointToChild(self.target, x, y)
|
||||
local directions = {
|
||||
@ -97,7 +109,7 @@ function Manager:init(args)
|
||||
end)
|
||||
|
||||
-- this should be moved to the device !
|
||||
Event.on('monitor_touch', function(h, side, x, y)
|
||||
singleThread('monitor_touch', function(h, side, x, y)
|
||||
if self.currentPage then
|
||||
if self.currentPage.parent.device.side == side then
|
||||
self:click(1, x, y)
|
||||
@ -105,7 +117,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('mouse_click', function(h, button, x, y)
|
||||
singleThread('mouse_click', function(h, button, x, y)
|
||||
|
||||
mouseDragged = false
|
||||
if button == 1 and shift and control then -- debug hack
|
||||
@ -123,7 +135,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('mouse_up', function(h, button, x, y)
|
||||
singleThread('mouse_up', function(h, button, x, y)
|
||||
|
||||
if self.currentPage and not mouseDragged then
|
||||
if not self.currentPage.parent.device.side then
|
||||
@ -132,7 +144,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('mouse_drag', function(h, button, x, y)
|
||||
singleThread('mouse_drag', function(h, button, x, y)
|
||||
|
||||
mouseDragged = true
|
||||
if self.target then
|
||||
@ -146,7 +158,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('paste', function(h, text)
|
||||
singleThread('paste', function(h, text)
|
||||
if clipboard.isInternal() then
|
||||
text = clipboard.getData()
|
||||
end
|
||||
@ -156,7 +168,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('char', function(h, ch)
|
||||
singleThread('char', function(h, ch)
|
||||
control = false
|
||||
if self.currentPage then
|
||||
self:inputEvent(self.currentPage.focused, { type = 'key', key = ch })
|
||||
@ -164,7 +176,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('key_up', function(h, code)
|
||||
singleThread('key_up', function(h, code)
|
||||
if code == keys.leftCtrl or code == keys.rightCtrl then
|
||||
control = false
|
||||
elseif code == keys.leftShift or code == keys.rightShift then
|
||||
@ -172,7 +184,7 @@ function Manager:init(args)
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('key', function(h, code)
|
||||
singleThread('key', function(h, code)
|
||||
local ch = keys.getName(code)
|
||||
if not ch then
|
||||
return
|
||||
@ -337,6 +349,9 @@ function Manager:click(button, x, y)
|
||||
button = 3
|
||||
self.doubleClickTimer = nil
|
||||
else
|
||||
if self.doubleClickTimer then
|
||||
debug(c - self.doubleClickTimer)
|
||||
end
|
||||
self.doubleClickTimer = c
|
||||
self.doubleClickX = x
|
||||
self.doubleClickY = y
|
||||
|
@ -103,7 +103,7 @@ function page.grid:draw()
|
||||
UI.Grid.draw(self)
|
||||
end
|
||||
|
||||
function eventLoop()
|
||||
Event.addRoutine(function()
|
||||
|
||||
while true do
|
||||
local e = { os.pullEvent() }
|
||||
@ -124,8 +124,7 @@ function eventLoop()
|
||||
page:sync()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
UI:setPage(page)
|
||||
Event.pullEvents(eventLoop)
|
||||
UI.term:reset()
|
||||
UI:pullEvents()
|
||||
|
@ -50,9 +50,11 @@ function page:eventHandler(event)
|
||||
Event.exitPullEvents()
|
||||
|
||||
elseif event.type == 'key' and event.key == 'enter' then
|
||||
if self.grid:getSelected() then
|
||||
showHelp(self.grid:getSelected().name)
|
||||
self:setFocus(self.filter)
|
||||
self:draw()
|
||||
end
|
||||
|
||||
elseif event.type == 'grid_select' then
|
||||
showHelp(event.selected.name)
|
||||
@ -80,5 +82,4 @@ function page:eventHandler(event)
|
||||
end
|
||||
|
||||
UI:setPage(page)
|
||||
Event.pullEvents()
|
||||
UI.term:reset()
|
||||
UI:pullEvents()
|
||||
|
@ -141,5 +141,4 @@ if not device.wireless_modem then
|
||||
end
|
||||
|
||||
UI:setPage(page)
|
||||
Event.pullEvents()
|
||||
UI.term:reset()
|
||||
UI:pullEvents()
|
||||
|
@ -476,7 +476,7 @@ UI:setPages({
|
||||
main = page,
|
||||
})
|
||||
|
||||
Event.addHandler('os_register_app', function()
|
||||
Event.on('os_register_app', function()
|
||||
loadApplications()
|
||||
page:refresh()
|
||||
page:draw()
|
||||
|
@ -201,11 +201,11 @@ function methodsPage.viewportConsole:draw()
|
||||
c.ymax = c.cursorY + 1
|
||||
end
|
||||
|
||||
Event.addHandler('peripheral', function()
|
||||
Event.on('peripheral', function()
|
||||
peripheralsPage:updatePeripherals()
|
||||
end)
|
||||
|
||||
Event.addHandler('peripheral_detach', function()
|
||||
Event.on('peripheral_detach', function()
|
||||
peripheralsPage:updatePeripherals()
|
||||
end)
|
||||
|
||||
@ -215,5 +215,4 @@ UI:setPages({
|
||||
methods = methodsPage,
|
||||
})
|
||||
|
||||
Event.pullEvents()
|
||||
UI.term:reset()
|
||||
UI:pullEvents()
|
||||
|
@ -62,12 +62,11 @@ function page.grid:getDisplayValues(row)
|
||||
return row
|
||||
end
|
||||
|
||||
Event.addTimer(1, true, function()
|
||||
Event.onInterval(1, function()
|
||||
page.grid:update()
|
||||
page.grid:draw()
|
||||
page:sync()
|
||||
end)
|
||||
|
||||
UI:setPage(page)
|
||||
Event.pullEvents()
|
||||
UI.term:reset()
|
||||
UI:pullEvents()
|
||||
|
@ -1,4 +1,5 @@
|
||||
require = requireInjector(getfenv(1))
|
||||
local Event = require('event')
|
||||
local UI = require('ui')
|
||||
local Socket = require('socket')
|
||||
local Terminal = require('terminal')
|
||||
@ -320,20 +321,6 @@ function page:enable()
|
||||
-- self.tabs:activateTab(page.tabs.turtles)
|
||||
end
|
||||
|
||||
local function updateThread()
|
||||
|
||||
while true do
|
||||
if page.turtle then
|
||||
local t = _G.network[page.turtle.id]
|
||||
page.turtle = t
|
||||
page:draw()
|
||||
page:sync()
|
||||
end
|
||||
|
||||
os.sleep(1)
|
||||
end
|
||||
end
|
||||
|
||||
if not Util.getOptions(options, { ... }, true) then
|
||||
return
|
||||
end
|
||||
@ -348,9 +335,17 @@ if options.turtle.value >= 0 then
|
||||
end
|
||||
end
|
||||
|
||||
Event.onInterval(1, function()
|
||||
if page.turtle then
|
||||
local t = _G.network[page.turtle.id]
|
||||
page.turtle = t
|
||||
page:draw()
|
||||
page:sync()
|
||||
end
|
||||
end)
|
||||
|
||||
UI:setPage(page)
|
||||
|
||||
page.tabs:activateTab(page.tabs[options.tab.value])
|
||||
|
||||
UI:pullEvents(updateThread)
|
||||
UI.term:reset()
|
||||
UI:pullEvents()
|
||||
|
@ -475,7 +475,7 @@ function Builder:getSupplies()
|
||||
return t
|
||||
end
|
||||
|
||||
Event.addHandler('build', function()
|
||||
Event.on('build', function()
|
||||
Builder:build()
|
||||
end)
|
||||
|
||||
|
@ -999,10 +999,8 @@ jobMonitor()
|
||||
jobListGrid:draw()
|
||||
jobListGrid:sync()
|
||||
|
||||
local function craftingThread()
|
||||
Event.onInterval(5, function()
|
||||
|
||||
while true do
|
||||
os.sleep(5)
|
||||
if not craftingPaused then
|
||||
local items = chestProvider:listItems()
|
||||
if Util.size(items) == 0 then
|
||||
@ -1023,8 +1021,7 @@ local function craftingThread()
|
||||
craftItems(craftList, items)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
UI:pullEvents(craftingThread)
|
||||
UI:pullEvents()
|
||||
jobListGrid.parent:reset()
|
||||
|
@ -4,7 +4,7 @@ local Socket = require('socket')
|
||||
local MEProvider = require('meProvider')
|
||||
local Logger = require('logger')
|
||||
local Point = require('point')
|
||||
local process = require('process')
|
||||
local Event = require('event')
|
||||
|
||||
if not device.wireless_modem then
|
||||
error('Modem is required')
|
||||
@ -16,14 +16,6 @@ if not turtle then
|
||||
error('Can only be run on a turtle')
|
||||
end
|
||||
|
||||
turtle.clearMoveCallback()
|
||||
|
||||
local gps = GPS.getPointAndHeading()
|
||||
if not gps then
|
||||
error('could not get gps location')
|
||||
end
|
||||
turtle.setPoint(gps)
|
||||
|
||||
local blocks = { }
|
||||
local meProvider = MEProvider()
|
||||
local items = { }
|
||||
@ -50,7 +42,7 @@ turtle.setMoveCallback(function(action, pt)
|
||||
for _,slot in pairs(slots) do
|
||||
if turtle.getItemCount(slot.index) ~= slot.qty then
|
||||
printError('Slots changed')
|
||||
process:terminate()
|
||||
Event.exitPullEvents()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -109,7 +101,8 @@ function gotoPoint(pt, doDetect)
|
||||
end
|
||||
|
||||
if doDetect and not turtle.detectDown() then
|
||||
error('Missing target')
|
||||
printError('Missing target')
|
||||
Event.exitPullEvents()
|
||||
end
|
||||
end
|
||||
|
||||
@ -254,14 +247,14 @@ local function pickupHost(socket)
|
||||
end
|
||||
end
|
||||
|
||||
process:newThread('pickup', function()
|
||||
Event.addRoutine(function()
|
||||
while true do
|
||||
print('waiting for connection on port 5222')
|
||||
local socket = Socket.server(5222)
|
||||
|
||||
print('pickup: connection from ' .. socket.dhost)
|
||||
|
||||
process:newThread('pickup_connection', function() pickupHost(socket) end)
|
||||
Event.addRoutine(function() pickupHost(socket) end)
|
||||
end
|
||||
end)
|
||||
|
||||
@ -304,10 +297,7 @@ local function eachClosestEntry(t, fn)
|
||||
end
|
||||
end
|
||||
|
||||
refuel()
|
||||
turtle.abort = false
|
||||
|
||||
local deliveryThread = process:newThread('deliveries', function()
|
||||
Event.addRoutine(function()
|
||||
|
||||
while true do
|
||||
if chestPt then
|
||||
@ -327,17 +317,17 @@ local deliveryThread = process:newThread('deliveries', function()
|
||||
end
|
||||
os.sleep(60)
|
||||
end
|
||||
|
||||
Event.exitPullEvents()
|
||||
end)
|
||||
|
||||
turtle.run(function()
|
||||
|
||||
while true do
|
||||
local e = process:pullEvent()
|
||||
if e == 'terminate' or deliveryThread:isDead() then
|
||||
break
|
||||
end
|
||||
if not turtle.enableGPS() then
|
||||
error('turtle: No GPS found')
|
||||
end
|
||||
|
||||
refuel()
|
||||
Event.pullEvents()
|
||||
|
||||
end)
|
||||
|
||||
process:threadEvent('terminate')
|
||||
|
@ -612,7 +612,7 @@ while not bExit do
|
||||
term.setTextColour(_colors.textColor)
|
||||
if #sLine > 0 then
|
||||
local result, err = shell.run( sLine )
|
||||
if not result then
|
||||
if not result and err then
|
||||
printError(err)
|
||||
end
|
||||
end
|
||||
|
@ -164,11 +164,10 @@ function changedPage:refresh()
|
||||
self.grid:draw()
|
||||
end
|
||||
|
||||
Event.addTimer(5, true, function()
|
||||
Event.onInterval(5, function()
|
||||
changedPage:refresh()
|
||||
changedPage:sync()
|
||||
end)
|
||||
|
||||
UI:setPage(changedPage)
|
||||
UI:pullEvents()
|
||||
UI.term:reset()
|
||||
|
@ -375,7 +375,7 @@ Message.addHandler('finished',
|
||||
Builder:finish()
|
||||
end)
|
||||
|
||||
Event.addHandler('turtle_abort',
|
||||
Event.on('turtle_abort',
|
||||
function()
|
||||
turtle.abort = false
|
||||
turtle.status = 'aborting'
|
||||
|
@ -30,7 +30,6 @@ end
|
||||
|
||||
local w, h = ct.getSize()
|
||||
socket:write({
|
||||
type = 'termInfo',
|
||||
width = w,
|
||||
height = h,
|
||||
isColor = ct.isColor(),
|
||||
@ -70,7 +69,7 @@ while true do
|
||||
|
||||
if filter[event] then
|
||||
|
||||
if not socket:write({ type = 'shellRemote', event = e }) then
|
||||
if not socket:write(e) then
|
||||
socket:close()
|
||||
break
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
print('\nStarting multishell..')
|
||||
print('\nStarting Opus..')
|
||||
|
||||
LUA_PATH = '/sys/apis'
|
||||
|
||||
|
@ -3,7 +3,7 @@ local function follow(id)
|
||||
require = requireInjector(getfenv(1))
|
||||
local Socket = require('socket')
|
||||
local Point = require('point')
|
||||
local process = require('process')
|
||||
local Event = require('event')
|
||||
|
||||
turtle.status = 'follow ' .. id
|
||||
|
||||
@ -20,8 +20,38 @@ local function follow(id)
|
||||
local lastPoint
|
||||
local following = false
|
||||
|
||||
local followThread = process:newThread('follower', function()
|
||||
while true do
|
||||
Event.on('turtle_follow', function(_, pt)
|
||||
|
||||
local pts = {
|
||||
{ x = pt.x + 2, z = pt.z, y = pt.y },
|
||||
{ x = pt.x - 2, z = pt.z, y = pt.y },
|
||||
{ x = pt.x, z = pt.z + 2, y = pt.y },
|
||||
{ x = pt.x, z = pt.z - 2, y = pt.y },
|
||||
}
|
||||
|
||||
local cpt = Point.closest(turtle.point, pts)
|
||||
|
||||
local blocks = { }
|
||||
|
||||
local function addBlocks(tpt)
|
||||
table.insert(blocks, tpt)
|
||||
local apts = Point.adjacentPoints(tpt)
|
||||
for _,apt in pairs(apts) do
|
||||
table.insert(blocks, apt)
|
||||
end
|
||||
end
|
||||
|
||||
-- don't run into player
|
||||
addBlocks(pt)
|
||||
addBlocks({ x = pt.x, z = pt.z, y = pt.y + 1 })
|
||||
|
||||
if turtle.pathfind(cpt, blocks) then
|
||||
turtle.headTowards(pt)
|
||||
end
|
||||
following = false
|
||||
end)
|
||||
|
||||
Event.onInterval(.5, function()
|
||||
|
||||
local function getRemotePoint()
|
||||
if not turtle.abort then
|
||||
@ -60,50 +90,16 @@ local function follow(id)
|
||||
if d < Point.pythagoreanDistance(turtle.point, pt) + 10 then
|
||||
lastPoint = Point.copy(pt)
|
||||
following = true
|
||||
process:newThread('turtle_follow', function()
|
||||
|
||||
local pts = {
|
||||
{ x = pt.x + 2, z = pt.z, y = pt.y },
|
||||
{ x = pt.x - 2, z = pt.z, y = pt.y },
|
||||
{ x = pt.x, z = pt.z + 2, y = pt.y },
|
||||
{ x = pt.x, z = pt.z - 2, y = pt.y },
|
||||
}
|
||||
|
||||
local cpt = Point.closest(turtle.point, pts)
|
||||
|
||||
local blocks = { }
|
||||
|
||||
local function addBlocks(tpt)
|
||||
table.insert(blocks, tpt)
|
||||
local apts = Point.adjacentPoints(tpt)
|
||||
for _,apt in pairs(apts) do
|
||||
table.insert(blocks, apt)
|
||||
os.queueEvent('turtle_follow', pt)
|
||||
end
|
||||
end
|
||||
|
||||
-- don't run into player
|
||||
addBlocks(pt)
|
||||
addBlocks({ x = pt.x, z = pt.z, y = pt.y + 1 })
|
||||
|
||||
if turtle.pathfind(cpt, blocks) then
|
||||
turtle.headTowards(pt)
|
||||
end
|
||||
following = false
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
os.sleep(.5)
|
||||
end
|
||||
end)
|
||||
|
||||
while true do
|
||||
local e = process:pullEvent()
|
||||
if e == 'terminate' or followThread:isDead() or e =='turtle_abort' then
|
||||
process:threadEvent('terminate')
|
||||
break
|
||||
end
|
||||
end
|
||||
Event.on('turtle_abort', function()
|
||||
Event.exitPullEvents()
|
||||
end)
|
||||
|
||||
Event.pullEvents()
|
||||
|
||||
socket:close()
|
||||
|
||||
@ -114,4 +110,3 @@ local s, m = turtle.run(function() follow({COMPUTER_ID}) end)
|
||||
if not s and m then
|
||||
error(m)
|
||||
end
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
local Socket = require('socket')
|
||||
local process = require('process')
|
||||
|
||||
local function wrapTerm(socket, termInfo)
|
||||
local function telnetHost(socket, termInfo)
|
||||
|
||||
require = requireInjector(getfenv(1))
|
||||
local Event = require('event')
|
||||
local methods = { 'clear', 'clearLine', 'setCursorPos', 'write', 'blit',
|
||||
'setTextColor', 'setTextColour', 'setBackgroundColor',
|
||||
'setBackgroundColour', 'scroll', 'setCursorBlink', }
|
||||
@ -11,10 +14,15 @@ local function wrapTerm(socket, termInfo)
|
||||
|
||||
for _,k in pairs(methods) do
|
||||
socket.term[k] = function(...)
|
||||
|
||||
if not socket.queue then
|
||||
socket.queue = { }
|
||||
os.startTimer(0)
|
||||
Event.onTimeout(0, function()
|
||||
socket:write(socket.queue)
|
||||
socket.queue = nil
|
||||
end)
|
||||
end
|
||||
|
||||
table.insert(socket.queue, {
|
||||
f = k,
|
||||
args = { ... },
|
||||
@ -26,54 +34,28 @@ local function wrapTerm(socket, termInfo)
|
||||
socket.term.getSize = function()
|
||||
return termInfo.width, termInfo.height
|
||||
end
|
||||
end
|
||||
|
||||
local function telnetHost(socket, termInfo)
|
||||
|
||||
require = requireInjector(getfenv(1))
|
||||
local process = require('process')
|
||||
|
||||
wrapTerm(socket, termInfo)
|
||||
|
||||
local shellThread = process:newThread('shell_wrapper', function()
|
||||
local shellThread = Event.addRoutine(function()
|
||||
os.run(getfenv(1), 'sys/apps/shell')
|
||||
socket:close()
|
||||
Event.exitPullEvents()
|
||||
end)
|
||||
|
||||
process:newThread('telnet_read', function()
|
||||
Event.addRoutine(function()
|
||||
while true do
|
||||
local data = socket:read()
|
||||
if not data then
|
||||
Event.exitPullEvents()
|
||||
break
|
||||
end
|
||||
|
||||
if data.type == 'shellRemote' then
|
||||
local event = table.remove(data.event, 1)
|
||||
shellThread:resume(event, unpack(data.event))
|
||||
end
|
||||
shellThread:resume(table.unpack(data))
|
||||
end
|
||||
end)
|
||||
|
||||
while true do
|
||||
local e = process:pullEvent('timer')
|
||||
|
||||
if e == 'terminate' then
|
||||
break
|
||||
end
|
||||
if not socket.connected then
|
||||
break
|
||||
end
|
||||
if socket.queue then
|
||||
if not socket:write(socket.queue) then
|
||||
print('telnet: connection lost to ' .. socket.dhost)
|
||||
break
|
||||
end
|
||||
socket.queue = nil
|
||||
end
|
||||
end
|
||||
Event.pullEvents()
|
||||
|
||||
socket:close()
|
||||
process:threadEvent('terminate')
|
||||
shellThread:terminate()
|
||||
end
|
||||
|
||||
process:newThread('telnet_server', function()
|
||||
|
Loading…
Reference in New Issue
Block a user