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

Doing stuff based on data from modems

Started by JohnnyX, 21 June 2013 - 10:31 AM
JohnnyX #1
Posted 21 June 2013 - 12:31 PM
So, I am making a replica of the Swan station from LOST and I want to create a program for the periscope that is basically a pc with a monitor in which monitor I want to print a red or green pixel next to a name of a sector of the station that will make me know if someone came down. I will put a proximity sensor block in key areas that will send a redstone signal to a pc that will send a message in a certain channel when it receives that signal. And that message will be picked by the periscope/PC and according to what the message was it will change the pixel colour near each sector name. Help? Here's what I wrote:

Periscope

term.clear()
mon = peripheral.wrap("back")
mon.setTextScale(0.5)
modem = peripheral.wrap("bottom")
modem.open(3)
mon.setCursorPos(1,1)
mon.write("Sector A ")
paintutils.drawPixel(8, 1, colour.lime)
mon.setCursorPos(1,4)
mon.write("Sector B ")
mon.setCursorPos(1,7)
mon.write("Sector C ")
while(true) do
local event, modemside, senderchannel, replychannel, message, senderdistance = os.pullEvent("modem_message")
if(message == "A") then
AlertA = paintutils.drawPixel(8, 1, colour.red)
end
end

Computer sending the message

modem = peripheral.wrap("top")
while(true) do
if(redstone.getInput("left") == true) then
modem.transmit(3, 1, "A")
end
end

Also I want to make a monitor/touchscreen that will control the lights. How can I do that? I know programming (C++) but I do not know Lua and I have not familiarized myself with the apis.

EDIT: The monitors for both the periscope and the light controler are 1 for each computer. Just a note :)/>/>
Lyqyd #2
Posted 21 June 2013 - 02:59 PM
Split into new topic.
Bomb Bloke #3
Posted 22 June 2013 - 08:05 AM
There's never any need to check if something "==true". If it already evaluates as "true", why perform the extra comparison? For eg, this is perfectly valid:

if(redstone.getInput("left")) then

Under Lua, you can also drop the brackets around the condition, if you like. But the "==true" thing is unnecessary under any language.

If a given program runs for more then about ten seconds without yielding ("waiting"), the Lua interpretor will kill it. Your periscope program yields once every iteration of its while loop thanks to the use of "os.pullEvent()", but your sending program doesn't yield at all.

Fortunately, every time a redstone input on the computer changes, that triggers an event. This means you can have the sending machine constantly yield while waiting for "os.pullEvent()" to pull that event, rather then spamming modem messages flat out.

Here's a proposed re-write for the loop on the periscope side:

while(true) do
  local event, modemside, senderchannel, replychannel, message = os.pullEvent("modem_message")

  if (message == "red") then
    paintutils.drawPixel(8, replychannel*3+1, colour.red)
  elseif (message == "green") then
    paintutils.drawPixel(8, replychannel*3+1, colour.lime)
  end
end

Note that you can omit variables you're not interested in when pulling a list of the things from a function. "message" is the last one we need from the os.pullEvent() statement, so "senderdistance" can be dropped.

Then on the other machines, our loop would be something like:

while(true) do
  if(redstone.getInput("left")) then
    modem.transmit(3, 0, "red")
  else
    modem.transmit(3, 0, "green")
  end

  os.pullEvent("redstone") -- Sit and do nothing until the redstone input changes.
end

Then on the next sensor machine, you'd use:

while(true) do
  if(redstone.getInput("left")) then
    modem.transmit(3, 1, "red")
  else
    modem.transmit(3, 1, "green")
  end

  os.pullEvent("redstone")
end

… and so on. Sure, this probably isn't the intended use of the "replyChannel" variable, but hey, why not?

It could be condensed down a fair bit more, if you're interested in seeing a few other concepts explained.

Fair warning, I haven't tried making a monitor yet, let alone tried this code, so I'm not 100% sure it'll all display as you want it to.
JohnnyX #4
Posted 24 June 2013 - 09:09 AM
Then on the next sensor machine, you'd use:

while(true) do
  if(redstone.getInput("left")) then
	modem.transmit(3, 1, "red")
  else
	modem.transmit(3, 1, "green")
  end

  os.pullEvent("redstone")
end

Well I actually want It all done in one pc. I'll just condense the code :)/> Thanks!
JohnnyX #5
Posted 24 June 2013 - 10:26 AM

  if (message == "red") then
	paintutils.drawPixel(8, replychannel*3+1, colour.red)
  elseif (message == "green") then
	paintutils.drawPixel(8, replychannel*3+1, colour.lime)
  end
end

What does the " replychannel*3+1" do?
EDIT: Nevermind I got it. Although it wont help me by using it, it's a great kickstart!
Also, should I use the paintutils function through a variable, like:


x = paintutils.drawPixel(8, replychannel*3+1, colour.red)
mon.write(x)


?

And what does the "0" represent in here and why is it being incremented? I want everything to happen (all the redstone signals) to go through one computer.


modem.transmit(3, 0, "red")

Bomb Bloke #6
Posted 24 June 2013 - 10:31 AM
It takes the value of "replychannel", multiplies it by three, then adds one to that.

So if "replychannel" is 0, the final result'll be 1, in line with Sector A. If "replychannel" is 1, the final result'll be 4, in line with Sector B. And so on.
JohnnyX #7
Posted 24 June 2013 - 11:25 AM
I cant really make it work, bellow is some moar code i made
JohnnyX #8
Posted 24 June 2013 - 12:15 PM
while(true) do
if(redstone.getInput("left")) then
modem.transmit(3, 1, "red")
else
modem.transmit(3, 1, "green")
end

os.pullEvent("redstone")
end

Here is some more code.


term.clear()
mon = peripheral.wrap("back")
mon.setTextScale(0.5)
modem = peripheral.wrap("bottom")
modem.open(3)
mon.setCursorPos(1,1)
mon.write("Sector A ")
mon.setCursorPos(1,4)
mon.write("Sector B ")
mon.setCursorPos(1,7)
mon.write("Sector C ")

while(true) do
local event, modemside, senderchannel, replychannel, message, senderdistance = os.pullEvent("modem_message")
  if(message == "A") then
	AlertA = paintutils.drawPixel(8, 1, colour.red)
	mon.write(AlertA)
  else
	SafeA =  paintutils.drawPixel(8, 1, colour.lime)
	mon.write(SafeA)
end
end


And this is the forwarding pc code:


term.clear()
term.setCursorPos(1,1)

m = peripheral.wrap("top")

print("Proximity Sensor Alert Forwarding Computer(P.S.A.F.C)")

while (true) do
  if (redstone.getInput("back")) then
	m.transmit (3, 1, "A")
	else m.transmit (3, 1, "!A")
	end

	os.pullEvent("redstone")
end



When it receives a redstone signal (the periscope), it crashes and says "atempting to index ? (a nill value). How do I fix it on this instance? Also, Any idea how I could easilly make buttons?

EDIT: Fixed. I replaced colour.red and colour.lime with their decimal values. But the colours appear only in the computer and not on the monitor and when either of them appear, the program ends.
Why so ?
Bomb Bloke #9
Posted 24 June 2013 - 07:02 PM
According to the paintutils API, it's for the displays of advanced computers only (those functions don't return anything you can print to a specific screen). I can't see any direct equavalent available for advanced monitors, so it looks like you'll have to make do with the term API.

I don't see any reason for either script to end. Do you get any errors?
theoriginalbit #10
Posted 25 June 2013 - 12:46 AM
According to the paintutils API, it's for the displays of advanced computers only (those functions don't return anything you can print to a specific screen). I can't see any direct equavalent available for advanced monitors, so it looks like you'll have to make do with the term API.


local monitor = peripheral.wrap("left")
paintutils.drawPixel(1, 1, colours.red) --# this is drawn on the computer
term.redirect(monitor)
paintutils.drawPixel(1, 1, colours.red) --# this is drawn on the monitor
term.restore()
paintutils.drawPixel(1, 1, colours.red) --# back on the computer again
JohnnyX #11
Posted 25 June 2013 - 03:35 PM
Yeah , thanks for pointing it out! Now i fixed it :D/> It works perfectly!!!