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

How do i run rednet.receive and still use the program

Started by VSXGsonic, 04 October 2014 - 01:33 AM
VSXGsonic #1
Posted 04 October 2014 - 03:33 AM
iv made an underground system and it has loads of doors and i can open them from pressing the button for that door on my pocket computer it looks like this

[ door 1] [door 2] [door 3]
[ door 4] [door 5] [door 6]

but i want it to update other peoples pocket computers when they run the door program so as i open and close door 1 that button on there's turns green to show its open then red for it closed. but when it waits for any rednet message it halts all the program so i carnt select anything till it receives is there a way to run the button update in the background so it does not effect what people are doing in the program??
Dragon53535 #2
Posted 04 October 2014 - 05:46 AM
You need os.pullEvent() You can use the door's ID to decide which one is sending the update.

local compid1 = 2 --#Some random computer ID
while true do
  local event, param1, param2 = os.pullEvent()
  if event == "rednet_message" then
    if param1 == compid1 then
	  if param2 == "I'mon" then
	    --#Door is on
	  elseif param2 == "I'moff" then
	    --#Door is off
	  end
    end
  end
end
Cycomantis #3
Posted 04 October 2014 - 06:49 AM
Using pullEvent() is not really the solution to this. You will want to look at the parallel API. Basically you will want it to look something like.

function main()
--put code for the door open/close here
end

function listen()
--put your rednet code here
end

parallel.waitForAny(main, listen)

Parallel API
Edited on 04 October 2014 - 04:52 AM
VSXGsonic #4
Posted 04 October 2014 - 06:58 AM
You need os.pullEvent() You can use the door's ID to decide which one is sending the update.

local compid1 = 2 --#Some random computer ID
while true do
  local event, param1, param2 = os.pullEvent()
  if event == "rednet_message" then
	if param1 == compid1 then
	  if param2 == "I'mon" then
		--#Door is on
	  elseif param2 == "I'moff" then
		--#Door is off
	  end
	end
  end
end
hmmm pull event works, but i have to send the im off or im on a few times before the computer picks it up . i know the pullEvent has a few second listen but is there away around it.


Using pullEvent() is not really the solution to this. You will want to look at the parallel API. Basically you will want it to look something like.

function main()
--put code for the door open/close here
end

function listen()
--put your rednet code here
end

parallel.waitForAny(main, listen)
iv never had any luck with the parallel.waitForAny as it locked it up and i need to be able to use the other buttons in the program as its waiting for the rednet_message to update colour (even if the door state never changes)
Bomb Bloke #5
Posted 04 October 2014 - 07:10 AM
Using pullEvent() is not really the solution to this.

Either method is valid. The most suitable one depends on what the button handling code looks like.
Edited on 04 October 2014 - 05:38 AM
Dragon53535 #6
Posted 04 October 2014 - 07:29 AM
hmmm pull event works, but i have to send the im off or im on a few times before the computer picks it up . i know the pullEvent has a few second listen but is there away around it.
os.pullEvent() stops the program until an event happens, be that a mouse click, a disk being put into a drive, or a rednet message, or anything in between. os.pullEvent() will halt the program until something happens, and then it will continue the program, however the while true do loop makes it so that if the event isn't what you're looking for, it starts over and calls os.pullEvent() again
VSXGsonic #7
Posted 04 October 2014 - 07:29 AM
this is just a code im using to test till all bugs sorted but same style


local screent = 100
mouseWidth = 0
mouseHeight = 0
monitor = peripheral.wrap("top")
w,h=monitor.getSize()

print(w)
print(h)
function home()
monitor.clear()
monitor.setCursorPos(1,1)
monitor.setBackgroundColour((colours.lime))
monitor.setCursorPos(2,2)
monitor.write("Door App")
monitor.setCursorPos(2,4)
monitor.write("  ")
monitor.setBackgroundColour((colours.black))
end
function door()
monitor.clear()
monitor.setCursorPos(1,1)
monitor.setBackgroundColour((colours.lime))
monitor.setCursorPos(2,2)
monitor.write(" open ")
monitor.setCursorPos(2,4)
monitor.write("closed")
monitor.setCursorPos(2,6)
monitor.write(" exit ")
monitor.setBackgroundColour((colours.black))
end
function homeClickPosition()
  if mouseWidth > 1 and mouseWidth < 10 and mouseHeight == 2 then
screent = 101

  elseif mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 4 then
  end
end
function doorClickPosition()
  if mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 2 then
rs.setOutput("right", true)
rednet.send (4,"door open", "doorapp")

  elseif mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 4 then
    rs.setOutput("right", false)
  elseif mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 6 then
   screent = 100
  end
end
function doorc()
local compid1 = 4 --#Some random computer ID
  local event, param1, param2 = os.pullEvent()
  if event == "rednet_message" then
    if param1 == compid1 then
		  if param2 == "I'mon" then
		  rs.setOutput("left", true) -- lights a lamp up while im still using buttons  --1 (will change these two to edit the button colour just easier to use lamp at the mo)
		  elseif param2 == "I'moff" then
		  rs.setOutput("left", false)-- turns the lamp off while im still using buttons--1
		  end
    end
  end
end

while true do
if screent == 101 then
end
----===== loads home screen
if screent == 100 then
home()
end
--=======
----===== loads door screen
if screent == 101 then
door() -- changes screen to next page
doorc() -- checks to see what state the door is sending out
end
--=======
local event,p1,p2,p3 = os.pullEvent()

 
   if event=="monitor_touch" then
  
	 mouseWidth = p2 -- sets mouseWidth
	 mouseHeight = p3 -- and mouseHeight
	
  if screent == 100 then
  homeClickPosition()
  mouseHeight = 99 -- coz it press the same place which opens a door when page door loads
	 end
 
  if screent == 101 then
  doorClickPosition()
	 end
 
   end
end
Cycomantis #8
Posted 04 October 2014 - 07:31 AM
iv never had any luck with the parallel.waitForAny as it locked it up and i need to be able to use the other buttons in the program as its waiting for the rednet_message to update colour (even if the door state never changes)

Do you have any code you can share, it should not lock up on you. I use the waitForAny() for uses very similiar to this without having any issues.
VSXGsonic #9
Posted 04 October 2014 - 08:13 AM
Do you have any code you can share, it should not lock up on you. I use the waitForAny() for uses very similiar to this without having any issues.
the code i posted works to my needs in away coz it has to be ready for multiple messages as i click buttons as someone may go through the door maybe 5 times and another door 2 so in stead of it checking once i need it to always be checking till i exit the door menu then it can stop checking that's why i limited it to the screent 101 which is when the door page is display.
Dragon53535 #10
Posted 04 October 2014 - 08:33 AM
Ahh you're wanting to be able to work with the program while you're editing, then that makes it slightly more difficult, and the parallel API would probably be the way to go.

Edit: i gave the program a quick read through, and i think i was wrong, let me read entirely
Edited on 04 October 2014 - 06:34 AM
VSXGsonic #11
Posted 04 October 2014 - 07:14 PM
yes i wanting to try and make it in to a kind of pda thing with different apps for lights. doors. reactor controls. gps and other stuff it just needs to be able to be ready for any message related to the app im in. kinda like facebook chat you can click names view details and stuff but when they come online the dot changes green and some dont come on at all just like my doors some will open 10 times in a minuet others like the test lab dont open at all some days but i want to see them show there open and closed or open on evryones pocket computer.

on a other thing my door when its open send this to the other computers with the program to update them
if door == change then
rednet.send(4,"mainDoor","doorSystem")
rednet.send(9,"mainDoor","doorSystem")
rednet.send(10,"mainDoor","doorSystem")
rednet.send(18,"mainDoor","doorSystem")
end
but it only wants to update 4 and not the others and some times wont update the rest till 9 starts the program to receive then it will continue :(/> i dont think it likes me -_-/>
Cycomantis #12
Posted 05 October 2014 - 02:33 AM
Okay so after looking through the code some I have some pointers on how to help you with some of the bugs you are seeing and help get you on your way to multitasking.


The reason why it currently takes you several attempts to receive the updates is you have two os.pullEvent()'s. One that has an if statement after if that discards anything other then a rednet message and one for monitor touches.

  local event, param1, param2 = os.pullEvent()
  if event == "rednet_message" then

--and
local event,p1,p2,p3 = os.pullEvent()
	if event=="monitor_touch" then

The problem this creates is that if a rednet message is received while the program is running the part of the code waiting for the monitor touch, the rednet message is discarded and nothing done with it.

A solution would be to combine the both doing something like

local event, param1, param2 = os.pullEvent()
  if event == "rednet_message" then
--do my rednet stuff
elseif event =="monitor_touch" then
--do that stuff
end

As far as your Door computers sending updates, Adding a small sleep inbetween the sends may help. But I would recommend changing to using channels for that portion of the code.

So on each PDA you would need to open the channel you are going to send to.

local channel = 1000 --whatever you want to use here
modem = peripheral.wrap(side)
modem.open(channel)
You will also need to update to listen for "modem_message" events instead of "rednet_message" events.

On your Door computer simply change to

local sendChannel = 1000 --same as in the PDA's
local myChannel = 1001
modem = peripheral.wrap(side)
modem.open(myChannel)
if door == change then
  modem.transmit(sendChannel,myChannel,"mainDoor") --use transmit and you should not need to use a protocol for this now
end
That way every computer with that channel open with receive the message.

Some of your if usage could be improved some as well. Here are some examples.

if screent == 101 then
end
----===== loads home screen
if screent == 100 then
home()
end
--=======
----===== loads door screen
if screent == 101 then
door() -- changes screen to next page
doorc() -- checks to see what state the door is sending out
end

--can be simplified to
if screent == 100 then
home()
----===== loads door screen
elseif screent == 101 then
door() -- changes screen to next page
doorc() -- checks to see what state the door is sending out
end

--and
  if screent == 100 then
  homeClickPosition()
  mouseHeight = 99 -- coz it press the same place which opens a door when page door loads
		 end

  if screent == 101 then
  doorClickPosition()
		 end

--down to
  if screent == 100 then
  homeClickPosition()
  mouseHeight = 99 -- coz it press the same place which opens a door when page door loads
  elseif screent == 101 then
  doorClickPosition()
  end
For the most part its always going to be best to use just 1 statement to do you checks. As you can see I've done that for everything here from the os.pullEvent() stuff to the screent if statements.

I will go through and see what I can do to try and figure out what your best approach is going to be in order to use the parallel.waitForAny() to accommodate your initial request.
EDIT: Before I do to much on that I would like to see what you end up with after making some of the possible changes I've suggested.
Edited on 05 October 2014 - 12:41 AM
VSXGsonic #13
Posted 05 October 2014 - 08:16 PM
i normally do combine my ifs but as i was getting annoyed with it i just kept putting in ifs and taking ifs till something worked then i could fix its position..
the modem.message messed me up abit at first as when it receives the first value is what side the message came from and i forgot it did that till i did a test and found out. oops

so far i played with the code to work one door and so far iv got this
PDA's code

local screent = 100
mouseWidth = 0
mouseHeight = 0
local button1 = "open"
local myChannel = 1000 --my receive channel im using here
modem = peripheral.wrap("back")
modem.open(myChannel)

function homes()
term.clear()
term.setCursorPos(1,1)
term.setBackgroundColour((colours.lime))
term.setCursorPos(2,2)
term.write("Door App")
term.setBackgroundColour((colours.black))
end
function door()
term.clear()
term.setCursorPos(2,1)
term.write("Door 1")
if button1 == "open" then
term.setBackgroundColour((colours.lime))
term.setCursorPos(2,2)
term.write(" open ")
term.setBackgroundColour((colours.black))
elseif button1 == "closed" then
term.setBackgroundColour((colours.red))
term.setCursorPos(2,2)
term.write("closed")
term.setBackgroundColour((colours.black))
end
term.setBackgroundColour((colours.lime))
term.setCursorPos(2,6)
term.write(" EXIT ")
term.setBackgroundColour((colours.black))
end
function homeClickPosition()
  if button == 1 and mouseWidth > 1 and mouseWidth < 10 and mouseHeight == 2 then
screent = 101
	end
end
function home()
homes()
event, button, p2, p3 = os.pullEvent()
   if event=="mouse_click" then
	 mouseWidth = p2 -- sets mouseWidth
	 mouseHeight = p3 -- and mouseHeight	
  homeClickPosition()
  --mouseHeight = 99 -- coz it press the same place which opens a door when page door loads
   end
end
function doorc()
-- Vall1 =sideReceived/button
-- Vall2 =receivedC/p2
-- Vall3 =sentFromC/p3
-- Vall4 =command/nill
event, Vall1, Vall2, Vall3, Vall4 = os.pullEvent()
if event == "modem_message" then
  if Vall3 == 1001 then
   if Vall4 == "open"then
	button1 = "open"
   elseif Vall4 == "closed" then
	button1 = "closed"
   end
  end
elseif event == "mouse_click" then
mouseWidth = Vall2 -- sets mouseWidth
	mouseHeight = Vall3 -- and mouseHeight
  if button == 1 and mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 2 then
   modem.transmit(1001,myChannel,"mainDoor")  
  elseif mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 6 then
   screent = 100
  end
end
end
while true do
if screent == 100 then	  ----===== loads home screen
home()
elseif screent == 101 then  ----===== loads door screen
door() -- changes screen to next page
doorc() -- checks to see what state the door is sending out/also/checks which button on door app is clicked
end
end
ans this is my door code

local channel = 1001 --my receive channel im using here
modem = peripheral.wrap("back")
modem.open(channel)
local myChannel = 1001
local open = 0
local lock = false
--============================
function door()
if open == 1 then
rs.setOutput("left", false)
modem.transmit(1000,myChannel,"open")
elseif open == 0 then
rs.setOutput("left", true)
modem.transmit(1000,myChannel,"closed")
end
end
--====
while true do
event, sideReceived,receivedC,sentFromC,command = os.pullEvent()
  if event == "modem_message" then
  if sentFromC == 1000 then
	if command == "mainDoor" then
		   if open == 1 then
		open = 0
	 elseif open == 0 then
			open = 1
	 end
		  end
  end
  door()
   end
print (command)
print(open)
end

so far its very responsive im going to make a few more doors and test it on them

EDIT: iv added two more doors to the system and it works just as fast as it would if i was using a lever its amazing :D/> :lol:/>.
Edited on 05 October 2014 - 10:29 PM
VSXGsonic #14
Posted 06 October 2014 - 04:14 AM
now i just need to find away to extend the transmit range as im at bedrock and there are doors 300+ blocks above me O-O and so far it just loops when i send -_-/>
Bomb Bloke #15
Posted 06 October 2014 - 04:22 AM
When two computers try to communicate (either sending or receiving), only the range of the highest computer matters.

Worst comes to worst, you should be able to stick a repeater system up at the very top of the world.
Cycomantis #16
Posted 06 October 2014 - 07:42 AM
In your home function you still have an os.pullEvent() which does not have any code to handle the modem messages. So there is still the potential of missing updates. I personally would try to find a way to eliminate that os.pullEvent() all together. If that is not possible then it will need some modem message code added in.

Here is an example of how to add in the parallel.waitForAny() into your code for you to play with.

local function modemMessage()
event, Vall1, Vall2, Vall3, Vall4 = os.pullEvent()
if event == "modem_message" then
    if Vall3 == 1001 then
        if Vall4 == "open"then
            button1 = "open"
        elseif Vall4 == "closed" then
            button1 = "closed"
        end
    end
end
end

local function mouseClickDoorc()
event, Vall1, Vall2, Vall3, Vall4 = os.pullEvent()
if event == "mouse_click" then
    mouseWidth = Vall2 -- sets mouseWidth
    mouseHeight = Vall3 -- and mouseHeight
    if button == 1 and mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 2 then
        modem.transmit(1001,myChannel,"mainDoor")  
    elseif mouseWidth > 1 and mouseWidth < 8 and mouseHeight == 6 then
        screent = 100
    end
end
end

local function mouseClickHome()
event, button, p2, p3 = os.pullEvent()
    if event=="mouse_click" then
        mouseWidth = p2 -- sets mouseWidth
        mouseHeight = p3 -- and mouseHeight    
    homeClickPosition()
    --mouseHeight = 99 -- coz it press the same place which opens a door when page door loads
    end
end
    
function home()
homes()
parallel.waitForAny(modemMessage, mouseClickHome)
end



function doorc()
parallel.waitForAny(modemMessage, mouseClickDoorc)
end
Edited on 06 October 2014 - 05:56 AM
VSXGsonic #17
Posted 06 October 2014 - 10:47 AM
When two computers try to communicate (either sending or receiving), only the range of the highest computer matters.

Worst comes to worst, you should be able to stick a repeater system up at the very top of the world.
already done both . it wont reach the top from bedrock and putting in repeaters only bounced thee same message around a door had a spaz as it opened and closed fast…

and as for home() not getting modem_message its meant to be like that as i only want it looking for door updates when its on the door screen as im going to put different screens on it ie tank monitor . reactor monitor. and gps and other stuff kinda like apps on a phone
Dragon53535 #18
Posted 06 October 2014 - 10:56 AM
You could easily build a system where the doors only send to the top one, and the top one distributes the information. Computer/repeater that is.
Edited on 06 October 2014 - 08:57 AM
wilcomega #19
Posted 06 October 2014 - 01:43 PM
the way the event system works in CC, any program or peripheral can add a event to the queue. once pullEvent is called it will return the first one in the queue and remove it.
when a rednet message is received it is simply put in the queue, if your server doesnt lag or your singleplayer doesnt lag, then the whole queue should be handled in no time, if you dont have delay built into your code.

so there is no way a incomming rednet message is lost
Bomb Bloke #20
Posted 06 October 2014 - 01:51 PM
so there is no way a incomming rednet message is lost

… so long as you don't discard the associated event while searching for one of a different type.
VSXGsonic #21
Posted 06 October 2014 - 08:40 PM
I have made a few computers to send the modem_messages further but one sends it the other receices it then that sends it to but the first gets it again to and they just back forth the message till I terminate them . I tried putting one high up but the message doesn't reach it

Edit: my place is about near hight limit and about 900 blocks wide. I know I could change the modem length but I would like to make an ingame way
Edited on 06 October 2014 - 06:44 PM
Lyqyd #22
Posted 06 October 2014 - 10:04 PM
That's exactly the situation the rednet API added message IDs to prevent. You'll need to use the rednet API and the repeat program or manually implement similar functionality for your program.
VSXGsonic #23
Posted 07 October 2014 - 12:35 AM
Done it had to make towers that sent the message from the bottom pc to the top then send it out with a value on the end and if the other tower picks it up it wont send to any value at the end. took a few times hitting head on desk to figure to do it that way. dont know why i didn't just do value correcting in the first place :wacko:/>.
wilcomega #24
Posted 07 October 2014 - 12:10 PM
in my oppinion rednet used to be a floppy system before it made use of the modem api. before taht point it would directly interact with the Java side of ComputerCraft, wich i just didnt like, now that they have transformed the modems into a proper peripheral, the system is much better, at the moment rednet is kind of a internet layer for the modems for you to use.

so what i would reccomend is that you use the rednet API instead of the modem directly as rednet right now is very powerfull, the only thing right now is security as there is no built in encryption system, like a public-private key encryption system.
but that is not really needed as not many people understand how to hack rednet.