Each of your scripts runs in a co-routine. When a script wants to get some sort of input - be it via the user, a modem, etc - it'll usually "yield", pausing its execution until ComputerCraft resumes it with "event" data. Events detail things like users pressing buttons, modem messages incoming, and so on. Usually,
os.pullEvent() is used to yield for event data.
When you call a function like read(), the code within that function pulls
key and
char events over and over until the user hits enter, and then returns a string describing the buttons pressed. When you call rednet.receive(), the code within that function does something similar, pulling all events from the front of the queue until a
rednet_message event appears there.
Functions like read() and rednet.receive() are what we call "event eaters" - new events are added to the end of a queue, and these functions pull and discard all events from the front of that queue until they get to the one they want. If a user types something while your script is executing rednet.receive(), for example, odds are the events for those button presses will be tossed out the window.
There are two ways of dealing with this problem. One is to write your own loop for handling key / char / rednet_message events, one that can handle all the relevant types for your script so that you don't have to call read() / rednet.receive(). read()'s a fairly complex function, though, so re-writing your own version is a fair bit of work.
A much easier way is to run more co-routines within your script, which can be resumed with a copy of all events your main script gets resumed by. If one of these is looking for keyboard events, and one for rednet events, then each can discard the ones it doesn't want without affecting the other.
The
parallel API makes this a lot easier: you can pass it multiple functions, and it'll run them as individual co-routines (switching execution between them whenever they pull an event by yielding). Eg:
local function getKeyboardInput()
while true do
--# read() messages from the user in front of the computer,
--# print them to the screen, and send them to the other user.
end
end
local function getRednetMessages()
while true do
--# Listen for rednet messages and print them to the screen.
end
end
parallel.waitForAny(getKeyboardInput, getRednetMessages) --# Note the lack of brackets after the function names.
The
window API is also worth a look - if you have one window for user input and one window for messages, then
redirect terminal output from one to the other immediately before and after writing out incoming rednet messages, you'll find it much easier to keep track of where the cursor should be.