Home

Awesome

ComputerCraft-EventLoop

An implementation of an Event Loop for ComputerCraft that provides an interface similar to Node.js's EventEmitter and setTimeout().

ComputerCraft-EventLoop is an API for Event-driven programming in ComputerCraft Lua that eliminates the need to create your own loop to capture events.

Current Version

ComputerCraft-EventLoop is currently at version 1.5

Installation

To install this program via pastebin, run

pastebin get RWaMMZVM eventloop

or go to http://pastebin.com/RWaMMZVM

ComputerCraft-EventLoop is also available on CCAPT

Usage

A program using ComputerCraft-EventLoop may look like this:

os.loadAPI('eventloop') --load the ComputerCraft-EventLoop API

local loop = eventloop.create() --get an EventLoop instance

loop:run(function () --run a function in the event loop
  print('I\'m in an event loop!')
  
  loop:timeout(2, function ()
    print('This will happen 2 seconds later.')
  end)
  
  loop:interval(1, function ()
    print('This will happen every second!')
  end)
  
  loop:on('char', 's', function ()
    print('You pressed s!')
  end)
  
  loop:timeout(6, function ()
    print('Goodbye') 
    loop:terminate() --stop the loop after 6 seconds
  end)
end)

Example output:

<img src="http://i.imgur.com/Vx4pxON.png">

API Documentation

eventloop.create()

Returns the EventLoop instance.

EventLoop

EventLoop:run([function])

Starts the event loop and executes the given function. This function will return once there are no more events to handle or the EventLoop is terminated.

Example:

loop:run(function () --start the loop
  loop:run(function () --calling run a second time doesn't create a second loop.
    --it's equivalent to EventLoop:timeout(0, function) if called while an event loop is running.
    print('Inner loop?')
  end)
end)

Returns the EventLoop instance.

EventLoop:running()

Returns the currently running listener (format described at EventLoop:listeners()) if the EventLoop is running, nil otherwise.

EventLoop:reset()

Removes all listeners and fired custom events from the EventLoop.

Returns the EventLoop instance.

EventLoop:timeout([time], function)

Starts a timer that executes the function after time seconds, defaulting to 0 seconds.

Example:

print('Shutting down')
loop:timeout(1, function () --leave time for people to read the message
  os.shutdown()
end)

Returns an id number that can be used to cancel the timeout.

EventLoop:interval([time], function)

Starts a timer that executes the function every time seconds, defaulting to 1 second.

Example:

print('send message to computer 2 regularly')
loop:interval(1, function ()
  rednet.send(2, 'still running')
end)

Returns an id number that can be used to cancel the interval.

EventLoop:cancel(id)

Cancels the timeout or interval with the given id.

Example:

print('send message to computer 2 regularly')
local heartBeatId = loop:interval(1, function ()
  rednet.send(2, 'still running')
end)
loop:once('rednet_message', 2, function (msg) --when receiving a message from 2
  if msg == 'stop' then --and the text is 'stop'
    loop:cancel(heartBeatId) --stop the heartbeat 
  end
end)

Returns the EventLoop instance.

EventLoop:on([eventType, [parameters...]], function)

Registers an Event Listener for the given event type. The function will be called every time the event is fired and the given parameters match. The function will be called with the additinal event parameters as arguments.

Additional event parameters are all the parameters of the event that you did not specify. i.e. if you want to handle only left clicks, you can specify the button parameter as 1, and receive only the x and y parameters as the button parameter would always be 1.

If no type is given, the function will be called for every event, regardless of type. Such Event Listeners will have the event type as the first argument.

Returns the EventLoop instance.

Example:

loop:on('mouse_click', 1, function (x, y)
  print('X-Pos: ' .. x .. ', Y-Pos: ' .. y)
end)
terminate Events

When ComputerCraft-EventLoop receives a terminate Event, the loop will automatically be terminated forcefully. If there is an Event Listener for terminate, the loop will continue as usual and will not be terminated.

error Events

When an Event Listener errors, ComputerCraft-EventLoop will fire an error event. If there is no Event Listener for the error event, the loop will be terminated with an error message. An error Listener will receive the error message as the first argument.

EventLoop:once([eventType, [parameters...]], function)

Same as on, except that the Event Listener is removed after the event is fired the first time. (i.e. the listener is only called once)

Example:

loop:once('terminate', function ()
  print('shutting down')
  os.shutdown()
end)

Returns the EventLoop instance.

EventLoop:off([eventType, [parameters...]], [function])

Removes the specified event listener for the given eventType and parameters. If no type is given, removes that Event Listener for every type of event. If no function is given, removes all Event Listeners for that type and parameters. If called without arguments, removes all Listeners.

Example:

loop:on('rednet_message', 2, function (msg)
  print('2 said: ', msg)
end)
loop:on('char', 'q', function ()
  loop:off('rednet_message', 2)
end)

Returns the EventLoop instance.

EventLoop:fire(eventType, [parameters...])

Fires the specified custom event with the given parameters. The only difference to standard computercraft events is, that these events can have more than 5 parameters.

Example:

loop:on('noFuel', function ()
  local slot = turtle.getSelectedSlot()
  turtle.select(1)
  turtle.refuel()
  turtle.select(slot)
end)
function checkFuel()
  if turtle.getFuelLevel() == 0 then
    loop:fire('noFuel')
  end
end

Returns the EventLoop instance.

EventLoop:defer(<time | [eventType, [parameters...]]>)

Defers execution of the current timeout or event handler. During waiting time, other event handlers may be called.

Example:

print('Press k!')
while true do
  local key = loop:defer('char')
  if key == 'k' then
    print('Correct!')
    break
  else
    print('Incorrect, try again.')
  end
end
print('Goodbye')
loop:defer(1) --leave time to read the message
os.shutdown()

Returns nil when called with time, and the additional event parameters when called with event parameters

EventLoop:listeners([eventType, [parameters...]])

Creates a list of listeners that listen for the given eventType and parameters.

The list is returned in this format:

{
  filter = <filter table>,
  fn = <function or coroutine>,
  type = <'on', 'once', 'deferred', or 'native'>
}

Returns the list of listeners

EventLoop:terminate()

Sends a terminate event to the loop that terminates the loop if it is not handled by any event listeners.

local count = 0
loop:on('terminate', function ()
  count = count + 1
  if count == 2 then
    print('Terminating')
    loop:kill()
  else
    print('Try again.')
  end
end)
loop:on('char', 't', function ()
  print('You pressed t...')
  loop:terminate()
end)

Returns the EventLoop instance.

EventLoop:kill()

Terminates the loop silently the next time the event listener yields.

Example:

loop:on('terminate', function ()
  loop:kill() -- supress 'Terminated' message if the program is terminated
end)
print('Try holding Ctrl+T.')

Returns the EventLoop instance.