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

read() persisting after parallel waitForAny returned a different function

Started by applesauce10189, 31 July 2017 - 06:43 PM
applesauce10189 #1
Posted 31 July 2017 - 08:43 PM
I'm playing with a lot of mods, I plan to have one central computer that controls many aspects of my base and gathers relevant statistics. None of that's actually in yet, because I was testing it before adding all that and encountered this issue.

The program's called startup so it boots up when you open the computer, and you're greeted with a password prompt. If you put in the password, you'll be taken to a placeholder prompt where read() is called, but I also used the parallel API's waitForAny to have a "logOut" function co-exist with the main function, so at any time I could press f1 to bring back the password prompt, or press f3 to kill the program entirely.

However, if I use f1 to bring back the password prompt, the read prompt from before is still accepting input, and basically providing an uncensored version of what should be asterisks. So basically I need a way to interrupt the read function that was called.



--uncomment this line when ready
--os.pullEvent = os.pullEventRaw
rednet.open("back")

--Set up the 'to do' list on the right monitors
mon = peripheral.wrap("right")
mon.clear()
mon.setCursorPos(1,1)
mon.setTextColor(colors.white)
mon.write("To do list:")
mon.setCursorPos(1,2)
mon.write("1: Finish the machinery line")
mon.setCursorPos(1,3)
mon.write("2: Begin project 'Alpha'")
mon.setCursorPos(1,4)
mon.write("3: Mine. Always need more everything")
mon.setCursorPos(1,5)
mon.write("4: Get a nether star")
mon.setCursorPos(1,6)
mon.write("5: Improve power armor")
mon.setCursorPos(1,7)
mon.write("6: Expand the 'to do' list")

--self explanatory
function myClear(color)
  term.clear()
  term.setCursorPos(1,1)
  term.setTextColor(colors.purple)
  term.write("AppleOS Master Computer")
  term.setCursorPos(1,2)
  term.setTextColor(color)
end

--Bring back the password screen, or kill the program entirely, if these buttons are pushed
function logOut()
  while true do
    blank = " "
key = " "
    blank, key = os.pullEvent("key")
if key == keys.f1 then
 parallel.waitForAny(password, logOut)
elseif key == keys.f3 then
 error("wut")
end
  end
end

--Require a password to access the heart of the computer
function password()
  while true do
    myClear(colors.white)
    term.setCursorPos(1,2)
    term.write("Password: ")
inPass = read("*")
if inPass == "yoloswag" then
 command()
else
 term.setCursorPos(1,3)
 term.setTextColor(colors.red)
 term.write("Nope.")
 sleep(3)
end
  end
end

--do all the fancy things I plan to do with this computer
function command()
  --while true do
    term.write("this is temporary.")
read()
  --end
end


parallel.waitForAny(password, logOut)



I did some research, is the coroutine API something I should look into? I'm very bad with programming, but I'm willing to learn it if that's how I gotta fix this
The Crazy Phoenix #2
Posted 01 August 2017 - 12:45 AM
Instead of using coroutines, try changing the os.pullEvent function to implement the behaviour you seek.


local killed = false
local oldPullEvent = os.pullEvent

function os.pullEvent(filter)
	while true do
		local event, r1, r2, r3, r4, r5 = os.pullEvent()
		--# In place of this comment, check if the event would trigger the custom behaviour and, if so, set killed = true and return an enter key event.
		if not filter or event == filter then
			return event, r1, r2, r3, r4, r5
		end
	end
end

local input = read()
if killed then
    --# Custom behaviour
else
    --# Enter pressed by the user
end
os.pullEvent = oldPullEvent

There are different ways of editing os.pullEvent to cause the behaviour you want. This is only one way of doing it.
Edited on 31 July 2017 - 10:47 PM
Dog #3
Posted 01 August 2017 - 01:52 AM
A quick and dirty fix would be to wrap your main parallel call in a while loop and replace the parallel call in logOut with a return. That'll cycle the main parallel call and start the routines over, abandoning the read call in command.

function logOut()
  while true do
    _, key = os.pullEvent("key")
    if key == keys.f1 then
      return --# instead of using parallel here, use a return to exit this function and cause the main parallel call to exit and restart
    elseif key == keys.f3 then
      error("wut")
    end
  end
end

...

--# main parallel call
while true do --# use a while loop to restart the parallel call if it exits
  parallel.waitForAny(password, logOut)
end
Edited on 31 July 2017 - 11:56 PM
applesauce10189 #4
Posted 01 August 2017 - 09:02 PM
A quick and dirty fix would be to wrap your main parallel call in a while loop and replace the parallel call in logOut with a return. That'll cycle the main parallel call and start the routines over, abandoning the read call in command.

function logOut()
  while true do
	_, key = os.pullEvent("key")
	if key == keys.f1 then
	  return --# instead of using parallel here, use a return to exit this function and cause the main parallel call to exit and restart
	elseif key == keys.f3 then
	  error("wut")
	end
  end
end

...

--# main parallel call
while true do --# use a while loop to restart the parallel call if it exits
  parallel.waitForAny(password, logOut)
end

Your solution works beautifully, thank you