· 6 years ago · Oct 16, 2019, 08:38 PM
1ComputerCraft EventLoop
2=======================
3
4An implementation of an Event Loop for ComputerCraft that provides an interface similar to Node.js's EventEmitter and ```setTimeout()```.
5
6ComputerCraft-EventLoop is an API for Event-driven programming in ComputerCraft Lua that eliminates the need to create your own loop to capture events.
7
8## Current Version ##
9
10ComputerCraft-EventLoop is currently at version 1.5
11
12## Installation ##
13
14To install this program via pastebin, run
15
16```pastebin get RWaMMZVM eventloop```
17
18or go to http://pastebin.com/RWaMMZVM
19
20ComputerCraft-EventLoop is also available on [CCAPT](https://github.com/LNETeam/CCAPT)
21
22## Usage ##
23
24A program using ComputerCraft-EventLoop may look like this:
25
26```lua
27os.loadAPI('eventloop') --load the ComputerCraft-EventLoop API
28
29local loop = eventloop.create() --get an EventLoop instance
30
31loop:run(function () --run a function in the event loop
32 print('I\'m in an event loop!')
33
34 loop:timeout(2, function ()
35 print('This will happen 2 seconds later.')
36 end)
37
38 loop:interval(1, function ()
39 print('This will happen every second!')
40 end)
41
42 loop:on('char', 's', function ()
43 print('You pressed s!')
44 end)
45
46 loop:timeout(6, function ()
47 print('Goodbye')
48 loop:terminate() --stop the loop after 6 seconds
49 end)
50end)
51```
52
53Example output:
54
55<img src="http://i.imgur.com/Vx4pxON.png">
56
57## API Documentation ##
58
59### ```eventloop.create()``` ###
60
61**Returns** the [EventLoop](#eventloop) instance.
62
63### ```EventLoop``` ###
64
65#### ```EventLoop:run([function])``` ####
66
67Starts the event loop and executes the given function.
68 This function will return once there are no more events to handle or the [EventLoop](#eventloop) is [terminated](#eventloopterminate).
69
70Example:
71
72```lua
73loop:run(function () --start the loop
74 loop:run(function () --calling run a second time doesn't create a second loop.
75 --it's equivalent to EventLoop:timeout(0, function) if called while an event loop is running.
76 print('Inner loop?')
77 end)
78end)
79```
80
81**Returns** the [EventLoop](#eventloop) instance.
82
83#### ```EventLoop:running()``` ####
84
85**Returns** the currently running listener (format described at [EventLoop:listeners()](#eventlooplistenerseventtype-parameters)) if the [EventLoop](#eventloop) is running, ```nil``` otherwise.
86
87#### ```EventLoop:reset()``` ####
88
89Removes all listeners and fired custom events from the [EventLoop](#eventloop).
90
91**Returns** the [EventLoop](#eventloop) instance.
92
93#### ```EventLoop:timeout([time], function)``` ####
94
95Starts a timer that executes the function after time seconds, defaulting to 0 seconds.
96
97Example:
98
99```lua
100print('Shutting down')
101loop:timeout(1, function () --leave time for people to read the message
102 os.shutdown()
103end)
104```
105
106**Returns** an id number that can be used to [cancel](#eventloopcancelid) the timeout.
107
108#### ```EventLoop:interval([time], function)``` ####
109
110Starts a timer that executes the function every time seconds, defaulting to 1 second.
111
112Example:
113
114```lua
115print('send message to computer 2 regularly')
116loop:interval(1, function ()
117 rednet.send(2, 'still running')
118end)
119```
120
121**Returns** an id number that can be used to [cancel](#eventloopcancelid) the interval.
122
123#### ```EventLoop:cancel(id)``` ####
124
125Cancels the [timeout](#eventlooptimeouttime-function) or [interval](#eventloopintervaltime-function) with the given id.
126
127Example:
128
129```lua
130print('send message to computer 2 regularly')
131local heartBeatId = loop:interval(1, function ()
132 rednet.send(2, 'still running')
133end)
134loop:once('rednet_message', 2, function (msg) --when receiving a message from 2
135 if msg == 'stop' then --and the text is 'stop'
136 loop:cancel(heartBeatId) --stop the heartbeat
137 end
138end)
139```
140
141**Returns** the [EventLoop](#eventloop) instance.
142
143#### ```EventLoop:on([eventType, [parameters...]], function)``` ####
144
145Registers an Event Listener for the given event type. The function will be called every time the event is fired and the given parameters match.
146 The function will be called with the additinal event parameters as arguments.
147
148Additional event parameters are all the parameters of the event that you did not specify.
149i.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```.
150
151If 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.
152
153**Returns** the [EventLoop](#eventloop) instance.
154
155Example:
156
157```lua
158loop:on('mouse_click', 1, function (x, y)
159 print('X-Pos: ' .. x .. ', Y-Pos: ' .. y)
160end)
161```
162
163##### ```terminate``` Events #####
164
165When ComputerCraft-EventLoop receives a ```terminate``` Event, the loop will automatically be terminated forcefully.
166If there is an Event Listener for ```terminate```, the loop will continue as usual and will *not* be terminated.
167
168##### ```error``` Events #####
169
170When 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.
171
172#### ```EventLoop:once([eventType, [parameters...]], function)``` ####
173
174Same as [on](#eventlooponeventtype-parameters-function), except that the Event Listener is removed after the event is fired the first time. (i.e. the listener is only called once)
175
176Example:
177
178```lua
179loop:once('terminate', function ()
180 print('shutting down')
181 os.shutdown()
182end)
183```
184
185**Returns** the [EventLoop](#eventloop) instance.
186
187#### ```EventLoop:off([eventType, [parameters...]], [function])``` ####
188
189Removes the specified event listener for the given eventType and parameters.
190If no type is given, removes that Event Listener for every type of event.
191If no function is given, removes all Event Listeners for that type and parameters.
192If called without arguments, removes all Listeners.
193
194Example:
195
196```lua
197loop:on('rednet_message', 2, function (msg)
198 print('2 said: ', msg)
199end)
200loop:on('char', 'q', function ()
201 loop:off('rednet_message', 2)
202end)
203```
204
205**Returns** the [EventLoop](#eventloop) instance.
206
207#### ```EventLoop:fire(eventType, [parameters...])``` ####
208
209Fires the specified custom event with the given parameters.
210The only difference to standard computercraft events is, that these events can have more than 5 parameters.
211
212Example:
213
214```lua
215loop:on('noFuel', function ()
216 local slot = turtle.getSelectedSlot()
217 turtle.select(1)
218 turtle.refuel()
219 turtle.select(slot)
220end)
221function checkFuel()
222 if turtle.getFuelLevel() == 0 then
223 loop:fire('noFuel')
224 end
225end
226```
227
228**Returns** the [EventLoop](#eventloop) instance.
229
230#### ```EventLoop:defer(<time | [eventType, [parameters...]]>)``` ####
231
232Defers execution of the current timeout or event handler. During waiting time, other event handlers may be called.
233
234Example:
235
236```lua
237print('Press k!')
238while true do
239 local key = loop:defer('char')
240 if key == 'k' then
241 print('Correct!')
242 break
243 else
244 print('Incorrect, try again.')
245 end
246end
247print('Goodbye')
248loop:defer(1) --leave time to read the message
249os.shutdown()
250```
251
252**Returns** ```nil``` when called with time, and the additional event parameters when called with event parameters
253
254#### ```EventLoop:listeners([eventType, [parameters...]])``` ####
255
256Creates a list of listeners that listen for the given eventType and parameters.
257
258The list is returned in this format:
259
260```lua
261{
262 filter = <filter table>,
263 fn = <function or coroutine>,
264 type = <'on', 'once', 'deferred', or 'native'>
265}
266```
267
268**Returns** the list of listeners
269
270#### ```EventLoop:terminate()``` ####
271
272Sends a terminate event to the loop that terminates the loop if it is not handled by any event listeners.
273
274```lua
275local count = 0
276loop:on('terminate', function ()
277 count = count + 1
278 if count == 2 then
279 print('Terminating')
280 loop:kill()
281 else
282 print('Try again.')
283 end
284end)
285loop:on('char', 't', function ()
286 print('You pressed t...')
287 loop:terminate()
288end)
289```
290
291**Returns** the [EventLoop](#eventloop) instance.
292
293#### ```EventLoop:kill()``` ####
294
295Terminates the loop silently the next time the event listener yields.
296
297Example:
298
299```lua
300loop:on('terminate', function ()
301 loop:kill() -- supress 'Terminated' message if the program is terminated
302end)
303print('Try holding Ctrl+T.')
304```
305
306**Returns** the [EventLoop](#eventloop) instance.