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

Error in openning modem channels

Started by Sivarias, 09 October 2013 - 10:47 AM
Sivarias #1
Posted 09 October 2013 - 12:47 PM
Title: Error in openning modem channels

What I'm attempting to do is on startup my computer will open all channels it can and it will be recieving messages from turtles (each having their own channel which is linked to thier computer ID)

I'm getting an error on line 26 saying I'm trying to index a nil value.

My code is here on pastebin

http://pastebin.com/Z5jC3sV3

Two for one, can you reset computer ids in the game?
CoderPuppy #2
Posted 09 October 2013 - 01:24 PM
`modem` is defined as local in the if statements so it only exists in them. You need to define modem before the ifs and just set it inside the if

local modem
if peripheral.getType('left') == 'modem' then
    modem = peripheral.wrap('left')
end
Sivarias #3
Posted 09 October 2013 - 01:27 PM
Sweet!! Thanks Coder Puppy. That was honestly the first time I've ever used local so I didn't think to look for that. Now to fix the same issue in the three other porgrams I hadn't tested yet…
Lyqyd #4
Posted 09 October 2013 - 01:27 PM
You're declaring the modem variable as local inside the if block. When the if block ends, the variable goes out of scope, so when you try to use modem.open later, it can't find it. You should declare it as local before the if block, then simply change the value inside it. Alternatively, since you're missing "front", you could iterate the list of sides:


local modem
for _, side in pairs(rs.getSides()) do
  if peripheral.getType(side) == "modem" then
    modem = peripheral.wrap(side)
    break
  end
end
Sivarias #5
Posted 09 October 2013 - 01:30 PM
Does anyone have an answer to my second question? can you reset ID's in game like labels?

What is the break line for?
Lyqyd #6
Posted 09 October 2013 - 01:30 PM
If you clear the label and break the turtle/computer, it will get a new ID next time it is placed.
CoderPuppy #7
Posted 09 October 2013 - 01:36 PM
You can't change a computer's id. But you can reset computer ids deleting <save>/computer/lastid.txt. This could mess stuff up… You could get computers with the same id.

break stops the loop, see http://www.lua.org/manual/5.1/manual.html#2.4.4.
Sivarias #8
Posted 09 October 2013 - 01:40 PM
Crap.. I was hoping to set up a system where the turtles were on channels 1-100 (and each channel was thier ID for easy rememberence) and the computers were 100+'s. Oh well

Edit: Secondary question, the _ after the for is just a variable correct?

Tertiary question, why is in pairs used?

Quadrary, why break the loop instead of waiting for it to end?
Sivarias #9
Posted 09 October 2013 - 08:42 PM
code

4 modem=peripheral.wrap("right")
5 print("Connected to Modem")



11 local channelMax=128
12for i=1, channelMax, 1 do
13 if not i==os.getComputerID() then
14 modem.open(i)
15 end
16 end

i'm getting an attempt to index a nil value at 4 when I run the code. Any idea what the issue is guys?
Yevano #10
Posted 09 October 2013 - 08:49 PM
Could you have overwritten the peripheral variable? Post the whole code, and put it in code tags.

Edit: Also, why are you opening 127 channels?
Sivarias #11
Posted 09 October 2013 - 09:07 PM

--This is a computer start-up program that will hopefully be able to control a veritable army of turtles.
print("Name: "..os.getComputerLabel())
print("ID: "..os.getComputerID())
modem=0
x="modem"
if peripheral.getType("left")==x then
		modem = peripheral.wrap("left")
		print("Modem is on the left")
elseif peripheral.getType("right")==x then
		modem = peripheral.wrap("right")
		print("Modem is on the right")
elseif peripheral.getType("top")==x then
		modem = peripheral.wrap("top")
		print("Modem is on the top")
elseif peripheral.getType("bottom")==x then
		modem = peripheral.wrap("bottom")
		print("Modem is on the bottom")
elseif peripheral.getType("back")==x then
		modem = peripheral.wrap("back")
		print("Modem is on the back")
else
		print("I don't have any modems")
end
local channelMax=128
for i=1, channelMax, 1 do
		modem.open(i)
end
print("")
print("I have the following programs available: ")
print("!tunnel, !refuel")
print("")
print("I will now wait for messages from Minions, hold Ctrl+T to terminate")
print("")
while true do
local event, modemSide, senderChannel,
  replyChannel, message, senderDistance = os.pullEvent("modem_message")
print("Message from Minion "..senderChannel.." : "..message)
end

This is the raw code before i tried to make it less universal and just work. I got it to work on the first computer (ID 0) but it won't work on this one (ID 2) and I don't understand why. I also want to pair it with another code that simply recieves messages and puts them on a large monitor as sort of a mission control. to that extent for this computer the last while loop has been deleted. and replaced with a shell.run("monitor code") and that while loop is in the monitor code.
Bomb Bloke #12
Posted 10 October 2013 - 01:38 AM
Saying "it won't work" isn't helpful. What does it do instead? What code are the turtles running? Does it give the same error as the code in your first post, or something different? If it's the same sort of thing on the same sort of line, reboot the computer and try it again.

Note that modems do not need to send to the same port they send from (nor should they), and connections to/from multiple devices can be managed through one port. That is to say, you need only open a port if you want to receive communications addressed to that port, and which port the communications are being sent from is irrelevant.
Sivarias #13
Posted 10 October 2013 - 12:39 PM
I've since tested the code on a single player server and it works beautifully. The error is still line 4, attempt to call nil. I think that with the issue setting up the server, the code somehow got corrupted. I will redownload it and try again. The turtles are using a very simple.


    modem.transmit(channel, channel, "Minion "..os.getComputerLabel().." has finished refueling, Sir!")

to send messages with the last set of quotes being changed as neccessary to report completing/starting of a tunnel/building/ditch/waterway etc.
Thank you for your input on channels. I just wanted to be able to track turtle by computer ID number so that way I know that when I send 1-5 to start mining, I can easily differentiate between 1 and say 3 finishing. I will open channel 128 on the turtles so that would be the channel they receive commands from.
Lyqyd #14
Posted 10 October 2013 - 01:15 PM
Threads merged. Please stick to one topic for all of your questions on a given piece of code.
Sivarias #15
Posted 10 October 2013 - 04:56 PM
Maybe this will be more clear.

When I run the following code

    --This is a computer start-up program that will hopefully be able to control a veritable army of turtles.
    print("Name: "..os.getComputerLabel())
    print("ID: "..os.getComputerID())
    modem=0
    for _, side in pairs(rs.getSides()) do
	  if peripheral.getType(side) == "modem" then
	    modem = peripheral.wrap(side)
	    print("Connected to Modem")
	    break
	  end
    end
    monitor=0
    for _, side in pairs(rs.getSides()) do
	  if peripheral.getType(side) == "monitor" then
	    monitor = peripheral.wrap(side)
	    print("Connected to Monitor")
	    break
	  end
    end
    drive=0
    for _, side in pairs(rs.getSides()) do
	  if peripheral.getType(side) == "drive" then
	    drive = peripheral.wrap(side)
	    print("Connected to Drive")
	    break
	 end
    end
    modem.open(100)
    modem.open(128)
    modem.open(os.getComputerID())
    print("")
    print("I have the following programs available: ")
    print("!tunnel, !refuel, !message, turtlestartup, !MissionControl, !chat")

in single player it works fine on multiple computers. However, when I upload it to a second computer in a server it says,

error in startup:4: attempt to index ? (a nil value)

all I'm doing in line 4 is defining a variable, so what is the issue? and why does it work in single player but not in multiplayer. is there a code issue there or what?
Sivarias #16
Posted 10 October 2013 - 05:17 PM
Resolved:
Apparently computers don't like rebooting with a disk drive that has a floppy in it connected
Bomb Bloke #17
Posted 10 October 2013 - 07:25 PM
Beats me how it'd give that error on that line, let alone what a monitor would have to do with it.

A couple of points, well done on your code improvements, but you can still trim things down a little bit. Eg, rather then having multiple loops checking for peripherals, one will do:

for _, side in pairs(rs.getSides()) do
  if peripheral.getType(side) == "monitor" then
	monitor = peripheral.wrap(side)
	print("Connected to Monitor")
  elseif peripheral.getType(side) == "drive" then
	drive = peripheral.wrap(side)
	print("Connected to Drive")
  elseif etc...

You may consider having each turtle open a port equal to its ID number (meaning that whenever a given turtle receives a message, odds are that message is specifically for that turtle). When booting up, they can send a message to the server stating their label, which the server can then store for later reference - or they can send a message requesting a label, which the server can make up based on what labels it's given out already. The point is to rig things so that you never need to manually code in new port numbers as you add turtles to the system.