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

Simple chat program

Started by tsquad23, 12 December 2015 - 09:02 PM
tsquad23 #1
Posted 12 December 2015 - 10:02 PM
I have two computers connected running a chat program i built. Everything is working however i want to add more functionality to the program. I want to add the ability to send and receive at the same time. Currently one system at a time waits for a message running os.pullEvent("message"). Once a new message is received it transmits that message onto the monitor and then hangs at io.read() waiting for the user to enter a message. During the time it is waiting at io.read() it cannot receive messages because os.pullEvent("message") is not being read. So i am looking for a way to perhaps run io.read() and os.pullEvnet("message") at the same time. Or perhaps have the program not hang at io.read().
Here is the program for reference….very first lua program mind you.

http://pastebin.com/GMRC0BbJ
Bomb Bloke #2
Posted 13 December 2015 - 01:09 AM
io.read() works by waiting for key/char events, and while it's executing, any other events (eg modem_messages) it pulls from the queue it simply discards.

The parallel API is the way to go here. That allows you to pass it multiple functions, which it'll run side-by-side: Whenever one yields (to pull event), it may pass control to the other (depending on whether it has a suitable event for it). All events get passed to both functions, so you can have one looking for only events of one type, another looking for events of only another type, and the two won't interfere.

You could, alternatively, build a single loop that listens for all event types and handles all of those you're interested in manually. Catch is you'd need to re-write io.read() from the ground up that way. The parallel API serves as a shortcut, but isn't always the best way to do this sort of thing.

Your next problem is managing the display: Say the user is midway through typing something, and suddenly you want to print a message that arrived via rednet. You need to pay attention to where io.read() had the cursor, go off and write the new message, and then put the cursor back!

The window API makes this sort of thing a little easier: You can actually divide up your screen real-estate into multiple "virtual" screens. When you factor in that your message area is eventually going to want to start scrolling, this makes it much easier to stop it from interfering with your typing area.

Here's a skeleton of the sort of structure you might use:

-- Open modem etc

local xSize, ySize = term.getSize()

local messageWindow = window.create(term.current(), 1, 1, xSize, ySize - 1)

local typingWindow = window.create(term.current(), 1, ySize, xSize, 1)

local function typeMessage()
	while true do
		modem.transmit(23,23,read())
	end
end

local function receiveMessages()
	while true do
		local event,modemside,senderChannel,replyChanne,message,senderDistance = os.pullEvent("modem_message")

		term.redirect(messageWindow)
		print(message)
		
		term.redirect(typingWindow)
		typingWindow.restoreCursor()
	end
end

term.redirect(typingWindow)

parallel.waitForAny(typeMessage, receiveMessages)