Hello dear community,
Today I'm writing a tutorial about the event system we can use in CC-Lua. I call the language CC-Lua, because normal plain Lua you install on your computer won't be compatible with a few function calls. For those who are not familair, CC stands for ComputerCraft.
So, what are events? Events are things you can trigger by clicking, hitting a key, scrolling your mousewheel and much more. The goal of this tutorial is to let you know how we can get the events, how we can use the events and why you want to use events.
For this tutorial you need to know what:Now, after this short introduction, lets start the tutorial!
Event Basics
So events are things that get triggered when something happens to the computer. For example, it could be your input, but also things like redstone could trigger an event. So almost anything that happens to the computer, can trigger an event. But this does not count for running code, actually, it can but we will get into that later.
To let our program know something is going to happen is using this function:
os.pullEvent()
This function is described on the wiki like so:
Boy, that is a lot of information at once. Lets forget the target-event for now, I want to explain the very basics first.
If we simply put os.pullEvent() plain in our code, it will wait for something to happen and then continue. So you cannot immediately print something after it. That code will look like this:
os.pullEvent()
print( "Hey, something happened to this computer!" )
Now if we want the information that happens, we have to catch that event first. That is going to look like this:
local event = os.pullEvent()
Basically we are creating a variable that catches what the os.pullEvent() returns. Just like you in the image read:
os.pullEvent(target-event) returns the event and any parameters the event may have.
Wait a minute, it can return parameters too? That means that os.pullEvent() can return multiple values! Per event it differs how many values get returned, so we do the max, which is 5 by the default events ( I will get into custom events later ), because we want to catch everything.
Usually, something like this gets done, it could be totally different since it are variables!
local event, value1, value2, value3, value4, value5 = os.pullEvent()
So we catch this in order:
- The event name
- The 1st event-value that gets returned
- The 2nd event-value that gets returned
- The 3rd event-value that gets returned
- The 4th event-value that gets returned
- The 5th event-value that gets returned
Now we can get into the argument os.pullEvent takes: string target-event (See the wiki image!)
This will say, that the argument is a string, so we need the quotes. Now what we can do, is pull only one event! So if you do not need an event that says that a peripheral gets attached, this is the solution. But there is one catch, you can only use that one type of event for those variables. So lets say we want the char event ( see the wiki page! ), we can simply do this:
local event, key = os.pullEvent( "char" )
We can actually name our arguments, because we know we are only to get the char event from this.
The point of this event system is, that you can do multiple stuff, without doing complicated things with coroutines (WARNING: This is advanced! Get into it when you're curious enough!).
We mainly use a while-loop to pull constantly events and process them. So, to create an infinite while-loop we do:
while true do
end
And do you remember that os.pullEvent() waits until something happened, or the target event gets hit? So does it here, it literally blocks the loop from looping until something happened.
Now, since we probably want to catch multiple events, it is going to be a plain os.pullEvent() with the catch variables. Like so:
while true do
local event, value1, value2, value3, value4 = os.pullEvent()
end
At this point, we can process the events, because we know what event happens. You create an if-elseif-end structure, and by the way you do remember you can look up the events with their values, right?
This is going to be your basic structure:
while true do
local event, value1, value2, value3, value4 = os.pullEvent()
if event == "eventName" then
elseif event == "otherEventName" then
end
end
You actually replace 'eventName' and 'otherEventName' with actual event names you looked up, right? :P/>/>/>/>
Within that if, you can process those values to your wishes.
Now I want to notify you on something that might be usefull to you, if you hate those ugly variable names like value1 etc. We can put the os.pullEvent() in one table, and then use the table to get your values:
while true do
local eventValues = { os.pullEvent() }
if eventValues[1] == "eventName" then
elseif eventValues[1] == "otherEventName" then
end
end
I will not get deep into this, but it might usefull to you.Okay, if you are still with me I will show you show some examples and explain the os.queueEvent function.
But first, the examples we can create with what we have learned today. Im going ahead and put the examples in a spoiler, since it will probably get long again. I dont want to over use the space this thread is already taking ;)/>/>/>
Examples:
Spoiler
Now first, let's make our own 'press a key to continue'. It is very easy to do, since it can be any key we only have to pull the 'key' event. So we are using the argument off os.pullEvent().
print( "Please press a key to continue!" )
os.pullEvent( "key" )
print( "You pressed a key, so lets continue!" )
There is not much going on in this code. Since we do not need the event name nor the key number we do not have to catch the events. We simply pull the 'key' event and just relax until someone hits the key!Now let's make a 'press a key to continue within 3 seconds' type of thing. This code is going to be partially commented, a comment in lua is with two dashes everything after that 'does not count for the code'.
And check out the timer event before you start understanding this, it will help you out!
local secondsPast = 0 -- A simple variable that will count for us
local timerID = os.startTimer( 1 ) -- A variable that holds the timer ID and starts the timer
print( "Press a key within 3 seconds" )
while true do
local event, value1 = os.pullEvent()
if event == "timer" and value1 == timerID then
secondsPast = secondsPast + 1 -- Increment secondsPast by one, a second has passed
if secondsPast == 3 then
break
-- 3 seconds have passed, lets break the loop and move on with the code.
else
timerID = os.startTimer( 1 )
-- Restart the timer
end
elseif event == "key" then
break
-- A key event occured, lets move on with the code, once again
end
end
if secondsPast == 3 then
print( "You did not press a key within the 3 seconds!" )
else
print( "You pressed the key!" )
end
If you understand the events by now, this code is a piece of cake! We simply increase a variable that holds the passed seconds, and we start a timer. Then we simply compare events and boom, we move on with the code and can check that variable again if the 3 seconds have passed. It is that simple!
Custom events
It is very simple to create custom events. The function you will use for that, as mentioned earlier, os.queueEvent(), but we need arguments.
Basically, the first argument is your eventname, and after that you pass variables you want to pass. The next time you are trying to os.pullEvent() it will show up!
Warning: functions like: read(), sleep() etc. empty the event stack and you will not be able to pull the event after that
So this is an example:
os.queueEvent( "testevent", 5 )
local event, value = os.pullEvent()
-- event -> testevent
-- value -> 5
Do whatever you need your own special event :)/> Oh, and by the way, you can simulate a keypress:
os.queueEvent( "key", 26 )
This probably wraps up this tutorial… for now.. :P/>
If you have any question please ask them! I will answer them A.S.A.P. and if they are usefull for other users I will put it in the tutorial self.
If I made any mistakes, please correct me! English is not my native language but I try my best :)/>
Thanks for reading,
- Engineer