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

listen to different messages from different pcs at once

Started by UrsaMauris, 07 April 2017 - 10:40 AM
UrsaMauris #1
Posted 07 April 2017 - 12:40 PM
Hello, I need help with a block of code which could make a computer listen to two different messages from two different pcs at once.

I wrote a few hundreds lines of code which allow me to randomly generate demand (for example 20x wheat) on one pc (lets call it company pc), on the other i programmed a bank account which can remember how much credits has someone on their acc and third pc which shows what demands are currently available (lets call this the HOME pc). The problem is in the HOME pc where the logic is as follows: pc listens to demands from company pcs (for example food company or tool company). The HOME pc can hold 5 demands at once. If there is a slot available, it sends the demanding company pc message, that there is a slot available. The company pc then sends their demand which is saved in the local file in the HOME pc. From this point on the HOME pc needs to listen to other demands from other company pcs as it now has still 4 slots available AND it has to listen to the original demanding company pc which tells our HOME pc if the demand was satisfied in which case the HOME pc deletes the demand.

So again, tldr, i need at the same time to simultaneously listen to two different messages with two different protocols at the same time.

Thanks folks
Bomb Bloke #2
Posted 07 April 2017 - 12:49 PM
Split from Idea Exchance.

Tables are your answer here - the idea is that when you receive a demand, you stick it into a table using the sender's ID as the index. When you receive future messages that aren't initiating a new connection, you check the sender IDs against those lodged in the table to quickly determine the place in the conversation.

It'd be a lot easier to show you a code example if you were to provide the code you've got so far.
UrsaMauris #3
Posted 07 April 2017 - 01:20 PM
Well I got a few hundred lines of code that I don't exactly want to write again if there isn't some easy way to copy/paste which I'm not aware of. But my basic idea is this:

Company pc: check for available slots in home pc. If there are available slots, generate random demand, show the demand in the company pc and ask for a password. Wrap the demand into a table and send over to the home pc. Wait until someone comes who fills the demand (puts the demanded things in the chest, its roleplay - trust based), enters the password, then send a message to the home pc to delete the demand, repeat after some time.

Home pc: look for 5 specific files corresponding to the 5 slots. If there are some files, unwrap them into a table and show it on screen. (– this will execute only at the start) Listen for availability check requests, if a request comes, check for available slots, if there are vacant slots, send a message to the company pc that it can send a demand. Listen for demand, when it comes, save it into a file and show it on the screen (rewrite the screen with current demands). Wait for canceling request after which delete the file, clear the slot for further use and rewrite the screen with current demands. Meanwhile listen for another check requests.
note: I'm a beginner so the logic might be a little off. Also the bold highlighted parts I have not coded yet. There will be many companies sorted into two categories: food and others. Accordingly the slots are divided into 2 slots for food and 3 slots for misc.

Additional question: wouldn't the system you proposed miss a check request in case the request would be sent in the precise time the program would check the table for match/mismatch of the id?

Thank you
Bomb Bloke #4
Posted 08 April 2017 - 02:31 AM
Well I got a few hundred lines of code that I don't exactly want to write again if there isn't some easy way to copy/paste which I'm not aware of.

The pastebin script can dump it online for you.

Additional question: wouldn't the system you proposed miss a check request in case the request would be sent in the precise time the program would check the table for match/mismatch of the id?

Technically that can't happen.

ComputerCraft runs all code through a single Lua VM. This VM assigns each system in the world (be it a turtle or a computer) a coroutine, and runs these one at a time.

Whenever a coroutine yields (pauses, basically), ComputerCraft then checks to see which systems are ready to be resumed and switches to one of them. In this way, only one system in your world is ever actually running code at any given moment - but execution can easily switch between many systems per second.

Systems yield in order to pull events, and ComputerCraft resumes them when it has the right event data for them. For example, if you call sleep(), the system starts a timer and sits back and waits for a "timer" event. If you call rednet.receive(), then the system attempts to pull a "rednet_message" event. read() has it wait for "key" and "char" events. Basically, any time your system is waiting for anything, it's yielding in order to do it.

Sometimes computers receive events more often than they yield. In this case the events go onto the end of a queue, and are removed from the front each time one is pulled. This means that even if a system has multiple messages sent to it during the space of one yield, it's still potentially able to rednet.receive() them all.

The only catch is if you attempt to pull an event of a certain type. Calling sleep(), for example, will have that function pull events over and over until it gets resumed with the timer event it wants - any messages in the event queue are simply discarded during this process, meaning you can't get them from rednet.receive() later on. There are ways to deal with this, but this particular problem really shouldn't be an issue for you with the setup you describe.
UrsaMauris #5
Posted 09 April 2017 - 10:22 AM
Ok, that is very well explained, thank you. Here is the Home pc code: https://pastebin.com/VHzNhQ4U . Again, I'm a beginner so the code and its logic surely is dumb, sorry for that. I'm a czech so some words like protocols and printed lines are in czech as well. If you want, I can upload the second pc's code (the company pc's) as well, but its code is even messier. I have another issue with this code - I wasn't able to make a function for saving the table into a file, loading it back from a file and print it out. I think I read sometime ago that it cannot be done, but I'd like a second opinion from a pro. Also, if you find any stupidities in the code, please, feel free to point them out.
Thanks again!

So I've tried to experiment a little with your idea, but a new type of error has emerged which I did not encounter before. Here is the pastebin: https://pastebin.com/qPbv9e62 . The error is specific in a way that I can only run the program I just wrote but when I terminate or the program ends on its own, I cannot edit it, cannot access /ls, I always get the Attempt to call nil error. I can upload the pastebin though. It's pretty annoying and I haven't been able to google this type of error, do you know something about it? It appeared after I started experimenting with tables inside a table. Thanks again

EDIT: so this is what have I come up with: https://pastebin.com/QNv5eqQj . Implemented the table system and it seems that you have saved me a lot of trouble :)/>

EDIT2: Solved the second problem with the Attempt to call nil error on calling /ls and /edit program. Apparently I used some variable which is also used by the system, in my case it was the "table" variable. I renamed it and it works just fine.
Edited on 09 April 2017 - 06:26 PM