Jump to content




os.pullEvent(): What is it and how is it useful?


51 replies to this topic

#1 Onionnion

    Lua Teacher

  • Members
  • 27 posts

Posted 30 April 2012 - 02:15 AM

os.pullEvent(): What is it and how is it useful?

For me, os.pullEvent() has proven to being one of the most useful tools available for ComputerCraft, but it can be quite confusing for many at first and I won't deny it for me as well (took me a couple days before I figured out how to use it properly..probably longer).

So what is os.pullEvent()?
os.pullEvent() is a function that's used to detect events of any type, which can be pressing a button on the keyboard or an incoming rednet message. For this brief guide I will just explain the basics of how it works and how to use it because of how easy it is to plug it in for other uses.
Hint:
Spoiler

A quick demonstration
Open a computer in Minecraft and enter the Lua command prompt ('lua' is the command as we should all know by now). Enter this short program:
while true do print(os.pullEvent()) end
After entering this feel free to press some buttons on your keyboard and you can see that it prints things like 'key30' or 'charj'.

What is it doing?
Basically what os.pullEvent() does is return values depending on certain inputs, or events, that happen, such as a keyboard button press or a redstone input. It returns these values based on this syntax:
event, param1, param2 = os.pullEvent() -- param = parameter
When os.pullEvent() is called, it waits, or "yields" for an input (depending on what's inside its parameters which in this case is nothing so it accepts all events; will cover this later) and once an input is recieved it applies it in like shown above.
Here's how the function works:

  • When called, it waits for an input (depending on parameter arguments)

  • Once an input is detected it sets a string to the first variable, which in this case is 'event', as the name of the event that occurred.

  • It then sets other parameters to other variables depending on the event type. These parameters and the number used is dependent on the event type.

Examples of usage:
Let's say you were developing a program that included key-pressing to choose options (press a to do this, press b to do that, etc.). How such a thing would be written is actually quite simple:
function clear(test) -- function to reset screen
	term.clear()
	term.setCursorPos(1,1)
	if test == nil then -- easy way to decide whether to display text or not
		print("Press 1 to say Hi, 2 to say Bye or 3 to exit.")
	end
end

clear()

while true do
	event, param1 = os.pullEvent()
	if event == "char" and param1 == "1" then -- if the event was a character input and the character pressed was 1
		print("Hi")  -- print "Hi"
		sleep(2)	 -- sleep for 2 seconds
		clear()	  -- call the clear function
	elseif event == "char" and param1 == "2" then -- if the event was a character input and the character pressed was 2
		print("Bye") -- print "Bye"
		sleep(2)	 -- sleep for 2 seconds
		clear()	  -- call the clear function
	elseif event == "char" and param1 == "3" then
		break -- breaks loop
	end
end -- will repeat until loop is broken with 'break' (3 being pressed)

clear(1) -- reset screen but without text

Another good example would be for detecting rednet messages:
side = "back"	 -- it's always good practice to set a variable to the side being used
rednet.open(side) -- opens that side's rednet port

function clear()  -- screen-clearing function
	term.clear()
	term.setCursorPos(1,1)
end

clear()

while true do
	event, param1, param2 = os.pullEvent("rednet_message") -- with rednet messages, the second variable is the ID of
														   --   the computer from which it was sent (integer) and
														   --   the third is the message itself (string)
														   -- parameter argument "rednet_message" limits the event
														   --   accepted to just "rednet_message"
	if param2 == "e" then -- if the message received is the string "e",
		break			 --   break the loop and exit
	end
	print(param1..": "..param2) -- if the loop isn't broke, it will print from which the ID came from and
								--   the message itself
end

clear() -- clear the screen before exiting
Hint:
Spoiler

Something to try:
Take the code of the first example and make it so it doesn't need 'event == "char"' in the boolean (true or false; if) operations.

All event types (from the events help file)
  • "char" when text is typed on the keyboard. Argument is the letter typed.
  • "key" when a key is pressed on the keyboard. Argument is the numerical keycode.
  • "timer" when a timeout started by os.startTimer() completes. Argument is the value returned by startTimer().
  • "alarm" when a time passed to os.setAlarm() is reached. Argument is the value returned by setAlarm().
  • "redstone" when the state of any of the redstone inputs change.
  • "disk" or "disk_eject" when a disk is entered or removed from an adjacent disk drive. Argument is the side.
  • "rednet_message" when a message is received from the rednet API.
Hint:
Spoiler

FAQ
(Idea for something to put here? Please share!)
How do I use Redstone events?? The Redstone event doesn't return any parameters!
if event == "redstone" and rs.getInput(side) == true then
	print("blah")
end


Understand yet? Feel free to ask any questions and I'll try my best to help. Any suggestions? Feel free to give! I'll also soon add more advanced ways to use this!

#2 Rwkeith

  • Members
  • 56 posts

Posted 03 May 2012 - 05:11 AM

Great guide. And this is one of the most useful commands in Computercraft =)

#3 EmTeaKay

  • Members
  • 115 posts

Posted 03 May 2012 - 10:43 PM

I thought you were asking what it was.

#4 DrEckenbecker

  • New Members
  • 7 posts

Posted 04 May 2012 - 02:46 AM

Fantastic guide. helped me a lot. The wiki needs some work on os.pullEvent()... I don't want to copy your guide, but it does seem to be wikiworthy :)/>

#5 Onionnion

    Lua Teacher

  • Members
  • 27 posts

Posted 04 May 2012 - 01:14 PM

 DrEckenbecker, on 04 May 2012 - 02:46 AM, said:

Fantastic guide. helped me a lot. The wiki needs some work on os.pullEvent()... I don't want to copy your guide, but it does seem to be wikiworthy :)/>
Currently we are working on the wiki and I am working on the OS API page and its functions: http://www.computerc...dpost__p__11434

Thanks!

#6 Smidge

  • New Members
  • 5 posts

Posted 08 May 2012 - 05:19 AM

Wow. My mind is blown with ideas now. Thanks.
Also, what is the difference between "char" and "key" events?

#7 BigSHinyToys

  • Members
  • 1,001 posts

Posted 08 May 2012 - 05:58 AM

 Smidge, on 08 May 2012 - 05:19 AM, said:

Wow. My mind is blown with ideas now. Thanks.
Also, what is the difference between "char" and "key" events?

"char" events return a string example "q" "y" "n"
"key" events return a number example 200 208 203 205
the numbers represent key in the case of the above.
200 is up key
208 is down key
203 is left key
and 205 is right key

In piratical use


local numb = 1
term.clear()
term.setCursorPos(numb,1)
print("Press q or Q to Quit")
term.setCursorPos(numb,2)
print("Press left key or right key to move text")
while true do
local event , param1 = os.pullEvent()
if event == "key" then
  if param1 == 203 then -- left key
  numb = numb-1
  end
  if param1 == 205 then -- right key
  numb = numb+1
  end
end
term.clear()
term.setCursorPos(numb,1)
print("Press q or Q to Quit")
term.setCursorPos(numb,2)
print("Press left key or right key to move text")
term.setCursorPos(numb,3)
if event == "char" and param1 == "q" or param1 == "Q" then
  print("Ended")
  break
else
  print("Not Ended")
end
end


#8 Onionnion

    Lua Teacher

  • Members
  • 27 posts

Posted 08 May 2012 - 01:34 PM

 Smidge, on 08 May 2012 - 05:19 AM, said:

Wow. My mind is blown with ideas now. Thanks.
Also, what is the difference between "char" and "key" events?
I'll ad that into the guide.
Thanks for answering his question, BigSHinyToys.

#9 DrFreenote

  • New Members
  • 7 posts

Posted 16 June 2012 - 03:09 AM

Hey, just a quick question for anyone who wants to answer; Regarding the key values, is there a comprehensible list of values and their associated key names? I've found one or two in various spots (it was mentioned above that "200" relates to the up arrow key, "208" relates to the down arrow key, et cetera), but I haven't actually found a list that clearly defines all the keys that will function.

EDIT: On that note, for those who are looking for a specific key value, open up the LUA console and type in the os.pullEvent("key") function. The value of the next key you press will show. (Though you all probably already know this and I'm just being silly.)

#10 MysticT

    Lua Wizard

  • Members
  • 1,597 posts

Posted 16 June 2012 - 06:28 PM

 DrFreenote, on 16 June 2012 - 03:09 AM, said:

Hey, just a quick question for anyone who wants to answer; Regarding the key values, is there a comprehensible list of values and their associated key names? I've found one or two in various spots (it was mentioned above that "200" relates to the up arrow key, "208" relates to the down arrow key, et cetera), but I haven't actually found a list that clearly defines all the keys that will function.

EDIT: On that note, for those who are looking for a specific key value, open up the LUA console and type in the os.pullEvent("key") function. The value of the next key you press will show. (Though you all probably already know this and I'm just being silly.)
Here's the list of key codes used by minecraft (and by extention, computercraft): wiki

#11 DrFreenote

  • New Members
  • 7 posts

Posted 16 June 2012 - 10:07 PM

Thank you very much, MysticT! This is exactly what I needed! =3

EDIT: I have another question out of curiosity, what would be the best way to detect simultaneous keystrokes? (Shift+Enter, Ctrl+Up, Ctrl+Shift+Tab, you get the idea.) Is it even possible? It's not a big thing, I can work around not being able to, though it would be rather helpful to know.

I figure this would relate to os.pullEvent(), though I'm not exactly sure how. I don't know of any way to detect when a key is released, though I could just be blindly overlooking something obvious.

#12 MysticT

    Lua Wizard

  • Members
  • 1,597 posts

Posted 16 June 2012 - 11:32 PM

 DrFreenote, on 16 June 2012 - 10:07 PM, said:

Thank you very much, MysticT! This is exactly what I needed! =3

EDIT: I have another question out of curiosity, what would be the best way to detect simultaneous keystrokes? (Shift+Enter, Ctrl+Up, Ctrl+Shift+Tab, you get the idea.) Is it even possible? It's not a big thing, I can work around not being able to, though it would be rather helpful to know.

I figure this would relate to os.pullEvent(), though I'm not exactly sure how. I don't know of any way to detect when a key is released, though I could just be blindly overlooking something obvious.
Currently there's no reliable way to do it. There should be a "key release" event or something, so we can keep track of the pressed keys, and detect combinations and other things.

#13 DrFreenote

  • New Members
  • 7 posts

Posted 17 June 2012 - 03:25 AM

Alright, good to know. Thanks again, MysticT!

#14 5olstitium

  • New Members
  • 2 posts

Posted 17 June 2012 - 04:48 AM

Can you explain os.pullEventRaw() vs os.pullEvent() please?

#15 DrFreenote

  • New Members
  • 7 posts

Posted 17 June 2012 - 06:26 AM

 5olstitium, on 17 June 2012 - 04:48 AM, said:

Can you explain os.pullEventRaw() vs os.pullEvent() please?
People can correct me if I'm wrong, but it seems the only notable difference is that os.pullEventRaw() will detect and allow intervention of termination, reboot, or shutdown events caused by the built in keybinds (Ctrl+T, Ctrl+R, and Ctrl+S respectively), whereas os.pullEvent() will not.

#16 Pinkishu

  • Members
  • 484 posts

Posted 17 June 2012 - 10:30 AM

 DrFreenote, on 17 June 2012 - 06:26 AM, said:

 5olstitium, on 17 June 2012 - 04:48 AM, said:

Can you explain os.pullEventRaw() vs os.pullEvent() please?
People can correct me if I'm wrong, but it seems the only notable difference is that os.pullEventRaw() will detect and allow intervention of termination, reboot, or shutdown events caused by the built in keybinds (Ctrl+T, Ctrl+R, and Ctrl+S respectively), whereas os.pullEvent() will not.

I think thats wrong :(/>

pullEventRaw and pullEvent are both defined in bios.lua btw

function os.pullEventRaw( _sFilter )
  return coroutine.yield( _sFilter )
end

function os.pullEvent( _sFilter )
  local event, p1, p2, p3, p4, p5 = os.pullEventRaw( _sFilter )
  if event == "terminate" then
    print( "Terminated" )
    error()
  end
  return event, p1, p2, p3, p4, p5
end

If you press Ctrl+R or Ctrl+S the mod itself handles the shutdown/reboot
If you press Ctrl+T a "terminate" is added to the event queue
Now If you call os.pullEvent as you see it will just call os.pullEventRaw and temrinate the program if it finds that event

So if you do os.pullEvent = os.pullEventRaw, what many people do to prevent Ctrl+T
you just reroute any os.pullEvent call to the direct os.pullEventRaw which does not check for the terminate event

#17 DrFreenote

  • New Members
  • 7 posts

Posted 17 June 2012 - 09:27 PM

Thank you for clearing that up, Pinkishu! =3

I do believe you saved me a million and one future headaches; I could have seen myself spending hours trying to figure out why my programs wouldn't prevent reboots or shutdowns.

On that note, referring to my earlier question regarding multiple keypresses, I spotted a predictable pattern in how keypresses are called. When a key is pressed, if that key contains a printable character, it will send two seperate events; The 'key' event, which outputs the key number, and the 'char' event, which outputs the character the key represents. The 'char' event can be used on it's own to detect Shift+[key] presses, as the character in question will be capitalized, though this is not reliable as CapsLock will then act as if Shift is perpetually being held (Quite possibly leading to false triggers). Unless there is a way to detect if CapsLock (or even NumLock) is activated, I wouldn't trust this method.

However, I've noticed a certain behavior when it comes to Ctrl+[key], assuming the key is normally associated with a 'char' event. The event in question simply refuses to trigger. Very consistantly, it seems. I wrote a little block of code as sort of an example, though I'm almost entirely sure there is a better way to accomplish this effect.

term.clear()
term.setCursorPos(1,1)
write("Key Testing Time")
local bLoopCheck = true
local bCtrlCheck = false
while bLoopCheck do
    local event,p1 = os.pullEvent()
    if event == "key" and p1 == 45 then -- 45 relates to the 'X' key
        bCtrlCheck = true
        os.queueEvent("ctrlchk") -- If bCtrlCheck is still true...
    elseif event == "char" and string.lower(p1) == "x" then
        bCtrlCheck = false
    elseif event == "ctrlchk" and bCtrlCheck == true then
        print("Ctrl+X pressed") -- ...Then trigger the event
        bCtrlCheck = false
        bLoopCheck = false -- End the loop
    end
end

Ctrl+X is the key combination that triggers the code, all it does for this example is loop through again, waiting for the next time Ctrl+X is pressed. Note that the 'ctrlchk' event will consistantly trigger after the 'char' event. If anybody knows of an easier / more efficient way of accomplishing this behavior, feel free to correct me.

#18 5olstitium

  • New Members
  • 2 posts

Posted 18 June 2012 - 02:33 AM

 Pinkishu, on 17 June 2012 - 10:30 AM, said:


BUNCHA INFO

So if you do os.pullEvent = os.pullEventRaw, what many people do to prevent Ctrl+T
you just reroute any os.pullEvent call to the direct os.pullEventRaw which does not check for the terminate event

Thanks for the explanation.

#19 Keetster

  • New Members
  • 3 posts

Posted 01 July 2012 - 01:13 AM

I get an error when trying to run a program based off of this

Error is: bios:206: [string "function"]:7: unexpected symbol

This is line 7: event, 3, param2 = os.pullEvent("rednet_message") -- 3 is the id of the sender, param2 is the string

The program is called function. Not sure if it matters.

#20 MysticT

    Lua Wizard

  • Members
  • 1,597 posts

Posted 01 July 2012 - 01:55 AM

 Keetster, on 01 July 2012 - 01:13 AM, said:

I get an error when trying to run a program based off of this

Error is: bios:206: [string "function"]:7: unexpected symbol

This is line 7: event, 3, param2 = os.pullEvent("rednet_message") -- 3 is the id of the sender, param2 is the string

The program is called function. Not sure if it matters.
Already answered in the post you made about this.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users