This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Kryptic's profile picture

[LUA | QUESTION] Detecting redstone while performing read()

Started by Kryptic, 08 January 2013 - 10:34 AM
Kryptic #1
Posted 08 January 2013 - 11:34 AM
Hi guys. I'm creating a program that needs to react to either an input from a bundled cable, or a number being typed into the terminal. But it needs to do both at the same time.
Here is an excerpt from my current code:


local y = nil
local z = 0
while z==0 do
term.clear()
term.setCursorPos(1, 1)
term.write("Type a number: ")
local event, param = os.pullEvent()
   if event == "key" then
	  if param ~= 1 and param ~= 28 then
		 y = tonumber(read())
	  end
	  if y~=nil then z = 1
	  end
   elseif event == "redstone" and rs.getBundledInput("back") and rs.getBundledInput("back")~=0 then
	  y = rs.getBundledInput("back") term.setCursorPos(1, 2) z = 1
	  y = 1+(math.log(y)/math.log(2))
   end
end
print(y)

The code works great, except if someone has typed in a string and then walked away without hitting enter. Then the "redstone" event won't activate because the computer is still doing read().

I tried to get it to detect the pressing of the escape key - the player quits looking at the terminal -and terminating the read() function, but I couldn't find a way of doing this while the read() command is still active.

What's the best way to solve this issue? Can the computer detect a second event if the first event's code hasn't finished executing?
remiX #2
Posted 08 January 2013 - 11:55 AM
Seeming as read() pauses a program because it uses os.pullEvent() so solving this can be done with os.pullEvent()

It will go something like this:
function readInput()
    while true do
        y = tonumber(read())
    end
end

function redstoneSignals()
    while true do
        event, param = os.pullEvent("redstone")
        if rs.getBundledInput("back") and rs.getBundledInput("back")~=0 then
            y = rs.getBundledInput("back") term.setCursorPos(1, 2) z = 1
            y = 1+(math.log(y)/math.log(2))
        end
    end
end

parallel.waitForAny(redstoneSignals, readInput)

Check it out here.
Kryptic #3
Posted 08 January 2013 - 01:18 PM
Fantastic! Knew there would be a way. Thanks for the help.
lologarithm #4
Posted 09 January 2013 - 12:41 PM
Out of curiosity since I am still pretty new to computercraft, would this work?

(There is some psuedo-code for values I don't know off the top of my head).

local buffer = ""
local y = nil
local z = 0
while z==0 do
term.clear()
term.setCursorPos(1, 1)
term.write("Type a number: ")
while true do
  local event, param = os.pullEvent()
  if event == "key" then
		 if param in range of number keys
				buffer = buffer .. (read number key)
				print character to screen as though typed
		 end
		 if param == 'enter key'
		   y = tonumber(buffer)
		   if y~=nil then z = 1
			 break
		   end
		 end
  elseif event == "redstone" and rs.getBundledInput("back") and rs.getBundledInput("back")~=0 then
	y = rs.getBundledInput("back") term.setCursorPos(1, 2) z = 1
	y = 1+(math.log(y)/math.log(2))
	break
  end
end
print(y)
ChunLing #5
Posted 09 January 2013 - 06:20 PM
Um…assuming that the pseudo-code bits are replaced with real code, I suppose it will allow you do enter a multi-digit number, which is stored as a string of digits and updated after each keypress, and when you hit enter that becomes a numerical value in y. At the same time, you're checking to see if a redstone event results in non-zero bundled input to the back of the computer.

If this happens before y has a numerical value, then an error will occur. And you don't really do much to ensure that y will have a numerical value if the user is being inept. But under certain circumstances it would work fine…I guess.

By the way, just pull the char events and get the digits. Only use the key event to catch the Enter key.
Edited on 09 January 2013 - 05:22 PM