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

Rednet.broadcast() And Rednet.receive() Woes (they're Really Slow)

Started by Nikola, 21 November 2013 - 08:34 PM
Nikola #1
Posted 21 November 2013 - 09:34 PM
Problem: rednet.receive() refuses to be triggered (not even tickled) and rednet.broadcast(); refuses to fire at times (most of the time…)
Context: I'm currently (once again) in the process of writting a reactor manager. im currently on the sensor data gather step. the issue here is that when i try to send An array of a reactor's contents, the data is generated, but not sent. nothing will pick it up when i try and send the data at more than one message a second.

Acknowledgement: i realize that i could just serialize the entire array and send it as a single string instead of sending it piece-meal to get around this whole issue, but i still want to know if this is just an API limitation, or something im doing wrong in my code.

heres my code…. I know its alot, i know my commenting isn't the greatest, but cut me some slack. I can't comment the thing like a story book because it just isn't finished yet, and im just a senior in highschool to boot…

Code: http://pastebin.com/xhGYpmUj

the issue im having can be traced specifically to the "netSendReactorMap()" function near the top of the program. the function that does the dirty work of sending off the generated data is handed to the "sendWords()" function. I think the problem is localized to those functions, i can't be sure. Before i put the filter on the"os.pullEvent()" command in my main method, the server was usually genrating all kinds of weird event records, which tells me i have NO idea how rednet really works.
so if in my comments i act like i know what im doing, i now stand corrected, because i don't.
Edited on 21 November 2013 - 09:15 PM
Nikola #2
Posted 21 November 2013 - 09:40 PM
ignore this reply, it was a mistake :| . However, please do not ignore the above post :)/>
Edited on 21 November 2013 - 09:18 PM
Kryptanyte #3
Posted 22 November 2013 - 06:40 AM
Why don't you send it all at once. I can't make out exactly what the issue you are having is, but something about the first message sends? and the rest don't?

Try putting the location, stack, name, damage into a table then textutils.serialize(table) then send that, so:


local rawTable = {location, stack, name, damage}

local sendTable = textutils.serialize(rawTable)

rednetFunction(sendTable)

Edited on 22 November 2013 - 05:40 AM
Bomb Bloke #4
Posted 22 November 2013 - 06:51 AM
In a nutshell, when a computer receives a rednet message, it goes into the event queue. When you use "rednet.receive()", all it's doing is pulling all events in the queue and discarding them until it finds a "rednet_message" event (or a suitable "timer" event, if you specified a timeout).

Because the rednet API is really just a wrapper for the modem API (it literally just calls into that API for you), not one but two events are fired on receiving messages: a rednet one, and a modem one. You can just ignore the extra.

Some other commands will pull events from the queue - for example, "sleep" starts a timer which fires an event after the specified time is up, and then sits there discarding all events in the queue until it gets the timer event it wants. Likewise for most any command that makes your script pause for any amount of time.

Which means that if the client sends a message to this system while it's sleeping (as it does while it itself is trying to send messages), then that sleep function will cause the message to be discarded. It may also be possible that a message is coming in when you've got the modem closed - since you're using it near constantly, I'd recommend leaving it open.

Difficult to comment further without seeing the client's code.

By the by, I'm not sure you understand what "textutils.serialize()" does - you use it on all the parameters passed to your "record" function, string or otherwise. Are you familiar with tables and arrays? Hopefully reading (and running) this demo code will be informative to you:

local myTable = {345,354}  -- Make a pre-filled table.
for i=1,#myTable do
  print(myTable[i])
end
print("")

myTable = {}  -- Make an empty table.
myTable[1] = 345354
myTable[2] = 234
myTable[3] = 34
print(myTable[3].." + "..myTable[2].." = "..(myTable[2]+myTable[3]))
print("")

local myString = textutils.serialize(myTable)  -- Convert the whole table into a single string.
print(myString) 
local myOtherTable = textutils.unserialize(myString) -- Convert it back.
print(myOtherTable[1])
print("")

local function myFunction(...)
  local parameters = {...}  -- Dump all parameters passed to this function into a table.
  for i=1,#parameters do
    print(parameters[i])
  end
  print("")
end

myFunction(452342,234,3)

os.queueEvent("someEvent",42,4,234)

myTable = {os.pullEvent("someEvent")}  -- Dump everything returned from this event into a table.
print(myTable[2])
Nikola #5
Posted 22 November 2013 - 04:32 PM
To Kryptanyte : that's pretty much what i was planning on doing. Like i said, i just want to figure out if this is something i'm doing wrong, or if this is just how things work.

To Bomb Bloke : The Thing with my "record()" function is that it's meant to record server activity by just printing it to the screen. I use the "textutils.serialize()" command to make sure that anything that i'm printing to the screen becomes a string before it reaches the print statements. I put them in there because occasionally i was getting arrays passed to the function, and when it tried to concatenate them with something else, the lua interpreter (or compiler, not really sure how lua works) would start throwing errors all over the terminal, so i just added that as security


Also, in general, the server is interfaced with using rednet messages, it waits for a message that matches one of the if statements in the main method. So to send a reactor map, the client send the message "sendReactorMap,1"
the main method picks up the message, the splits it up into "sendReactorMap" and "1". The "1" at the end tells the server which reactor map to return.

this is just a weird thing i just now noticed while fixing my code…
i had two "getStorageX()" functions, and one of them was empty.
i have no idea where it came from, im just going to assume that both lua and i had a massive brain fart when that part came around, because im pretty sure lua shouldn't allow a double definition of a function…
Edited on 22 November 2013 - 03:48 PM
Nikola #6
Posted 23 November 2013 - 05:00 PM
alright, here is the client code

http://pastebin.com/Y0xBrhB4

and heres the new server code

http://pastebin.com/z8JwJUyB

Discovery: while testing the server and client just a little while ago, i finally got the client to pick up the reactorMap.
However, the strange part of about it was that i had to restart the server with the client still running for the client to
pick it up. Any Ideas on this?

Just a quick update:
I figure since im going full hog into it this time, i might as well post some picks of the map and facility in which i've been designing this reactor code inside of
also, i should probably mention that i've already designed and built the actual reactor set up that this program is meant to manage. this isn't to say that that
design is final, its simply to say that it exists

Here is a link to my photobucket so you can see all of the photos, i would embed them all in the post, but there are just too many

http://s804.photobucket.com/user/weekendmodder/library/Reactor%20Photos

there is an image of the output of the reactor prototype debug console in there if anyone is interested as well as some photos i took of a much older reactor manager that i had written, but was too unmanageable to ever even finish…
Edited on 23 November 2013 - 04:55 PM
Bomb Bloke #7
Posted 23 November 2013 - 07:38 PM
I use the "textutils.serialize()" command to make sure that anything that i'm printing to the screen becomes a string before it reaches the print statements. I put them in there because occasionally i was getting arrays passed to the function, and when it tried to concatenate them with something else, the lua interpreter (or compiler, not really sure how lua works) would start throwing errors all over the terminal, so i just added that as security
Er, I guess this was before you started using "record" for events only?

I'd be curious to know what sort of "weird event records" you were previously getting.

this is just a weird thing i just now noticed while fixing my code…
i had two "getStorageX()" functions, and one of them was empty.
i have no idea where it came from, im just going to assume that both lua and i had a massive brain fart when that part came around, because im pretty sure lua shouldn't allow a double definition of a function…
It does. Unlike eg Java's methods, think of Lua's function declarations as being the same as declaring any other variable: You can't use them until you've set them, and you can later set them to something else, if you like.

You can even use a variable as a table, turn it into a function, then put a string in it instead. Whatever. Obviously what you "can" do is often far removed from "good practises", but the options are there - the main thing to keep in mind is that this means giving a "regular" variable the same name as a "function" causes a conflict.

Discovery: while testing the server and client just a little while ago, i finally got the client to pick up the reactorMap.
However, the strange part of about it was that i had to restart the server with the client still running for the client to
pick it up. Any Ideas on this?

… Speaking of declaring functions, I see that you try to refer to some of your functions before you've declared them. The only reason this works at all is because you don't declare your functions as local (which has a side effect of causing them to stay loaded in RAM after the script exits out).

You'd localise them like this:

local function netSendReactorMap(react)

Then make sure that every function declaration that makes use of another function in your script, is declared after that other function has been declared.

That is to say, for much the same reason this won't work:

local c = a + b
local a = 3
local b = 5
print(c)

… nor will this:

local function c()
  return a() + b()
end

local function a()
  return 3
end

local function b()
  return 5
end

print(c())

Although your current implementation probably isn't the source of all (or more likely any of) your problems, I suspect it's still worth cleaning up.
Nikola #8
Posted 24 November 2013 - 02:59 AM
First Off, I'd Like To Say Thank You! I Had No Idea That Lua Functions Worked Like That! I Thought All Functions Get Initialized Before Any Code Gets Executed. I Always Figured That Because Lua Would Force Me To Put The Functions Before My Main Method. But What You're Saying Makes A Ton Of Sense! I've Just Never Thought About It That Way Because I've Never Really Worked In A Language Like Lua Before… Also, I Think That Would Localization Issue You Were Talking About Might Have Something To Do With My Problems. Every Time My Network Would Just Completely Stop Functioning, I Would Have To Completely Reboot All Of The Computers On It. I'm Probably Totally Off Target, But I Guess It Gives Me Some Path To Look Down In Terms Of Ferreting Out My Issue. So Yeah, I'll Have Plenty Of Things To Keep Me Busy On This Project.

All I Really Hope For Is That This Version Of My Reactor Manager Project Doesn't Get Totally Out Of Hand And 'Unmanageable' Like My Last One Did. The Code Was Confusing, Overly-Complicated, And Caused Minecraft To Tank From 120+ FPS All The Way Down To 25 FPS And Lower… So Far, This Version Has None Of Those Issues, … Yet.

Something Worrisome: After Concluding My Failure State Testing Under The Worst Cast Scenario, I Found Out That Should Really Any Part Of My Reactor Manager Fail, I Could End Up With A Smoldering Green Crater About 125 Meters In Diameter. That Is Assuming That The Reactor Stayed Between 85% And 99% Long Enough To Melt The Reactor Core's Casing, But Not The Active Cooling Systems, Then Hit Critical. While Unlikely, It's Food For Thought About How Careful You Should Be With Nuclear Reactors.
Edited on 24 November 2013 - 01:19 PM