ComputerCraft Routing

  • The FTB Forum is now read-only, and is here as an archive. To participate in our community discussions, please join our Discord! https://ftb.team/discord

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
So, I have a cart system running to my Ars Magicka area, and to my mining area. I'd like to be able to set up a pair of computers connected via-wireless modem so I can enter the name of a destination on the computer in my train station and be directed either to the Ars Magicka area, or to the mining area. The switch track and switch lever is less than 64 blocks from the area I want the computer, so it shouldn't be a problem. I just don't know how to do the programming. I've never been able to get a computer to function properly with a wireless modem in any of my coding. Modem would be on the bottom on both computers and Mining would be no signal and Ars Magicka would be positive signal. Can anyone help me?
 

Algester

New Member
Jul 29, 2019
378
0
0
this is actually easier done with wireless redstone :X and a rd net peripheral... but that's my advise if you actually know how to code with wireless redsone in the mix
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
If I'd only thought of that before I used my only two Ender Pearls on the modems... I guess I'll have to go hunting for more. I'd still like to be able to figure out how to do it with Computercraft modems, since I can think of a few other things I'd like to be able to automate that way.
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Another way to do it if you are using locomotives is to have a ticket machine from open peripherals which you can write a program for to print single use tickets for. I know that's not what you asked for but I thought I would mention it anyway.

To answer your real question though, this is the gist of how its done.
By the way, I prefer the modem api to the rednet api so I will use that.

Here is a goodway to wrap a modem (it can be easily adapted to make use for other peripherals too. You can also add an isWireless() check if you want)

Code:
function wrapOnePeripheral(pType) -- pType is the name of the peripheral.*
    local wrap = nil
    for i, v in pairs(peripheral.getNames()) do -- Searches through every peripheral
        if peripheral.getType(v) == pType then -- Checks if that peripheral is a pType
            wrap = peripheral.wrap(v) -- Wraps the peripheral
        end
    end
    return wrap -- Returns the peripheral handle that you can store
end

--[[* Finding the right name for a peripheral can be a bit tricky sometimes but in vanilla computercraft the names are straightforward. Wired and wireless modems are both called "modem"]]

local modem = wrapOnePeripheral("modem")

Using that function means you don't need to worry about which side a peripheral is on (it also works for peripherals connected via wired modem)

Sending a message with the modem api is easy. You need three pieces of information, the sending channel, the reply channel and the message

Code:
local sendChannel = 100
local replyChannel = 101
local message = "Hello"

modem.transmit(sendChannel, replyChannel, message)

Any computer listening to sendChannel will be able to receive that message as a "modem_message" event

You can open and close modem channels to enable or disable listening on that channel. Capture a message by waiting for the "modem_message" event

Code:
modem.open(sendChannel)
local event = {os.pullEvent("modem_message")} -- All the variables returned by the modem message will be captured inside a new table called event

--[[ event table structure
event = {
[1] = string eventDescription, - "modem_message"
[2] = string modemSide,
[3] = number sendChannel,
[4] = number replyChannel,
[5] = string message,
[6] = number distance,
}
]]

--Event gets fired as message is received!

local messageReceived = event[5]

Arrange for the computer that controls the junction to receive a message like this. Then you can run a condition based on the message to make the computer do what you want for example:

Code:
if messageReceived == "hello" then
   modem.transmit(replyChannel, sendChannel, "Hello to you too")
   redstone.setOutput("right", true)
else
   print("The message I got was not what I expected")
   redstone.setOutput("right", false)
end

Put the event code inside a while loop to make it work forever.

You can send serialised tables to send more complicated information. This can allow you to set up a complicated filter so if you are controlling multiple junctions with the same main computer you have a way of making sure the right message is only interpreted by the right computers.

If there are any more specifics that you want to discuss I will be happy to do so. I am designing a similar program right now.

p.s. I haven't tested any of the code above so there might be errors but the general idea is correct. That does not apply to the wrapOnePeripheral function though. That should work fine
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
When my mining area goes automated, I'll be using locomotives. For now, I'm using a drivable Steve's Cart, and my computer lags such that it really doesn't like the SC2 Junction Tracks. But switch tracks work just fine. As soon as I get back to my Minecraft computer, I'll test out that code. Is it possible to have computers 'pass the message', by sending a signal upon receipt of one? So if I have two junctions, one going to the Ars Area, one to the Mining Area, and a branch from the Mining Area, set up so I could have the Ars branch track pass the signal along so that both junctions are set correctly?

Also, that modem code is pretty ingenious.
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Is it possible to have computers 'pass the message', by sending a signal upon receipt of one? So if I have two junctions, one going to the Ars Area, one to the Mining Area, and a branch from the Mining Area, set up so I could have the Ars branch track pass the signal along so that both junctions are set correctly?

What you ask is possible but I think that it might be better to write a "route" into the main computer (which I will refer to as the server now, the junction controllers are clients). The advantage of this is that you only have to update the server program to add new destinations. I thought a little bit about this possibility as I was writing the last post and this is what I came up with.

Each destination has a table attached to it in the code. For the sake of argument, I will call this table route. The route table contains a key reference to every single junction you have that the cart will pass over on its journey. So the junction name will be stored in the key and then inside that key there will be information about how to contact that junction (for example the frequency it operates on, or a string filter that you added) and also a boolean that represents the redstone state that junction needs to have.

Here is an example based on a journey from New York to Los Angeles.

Code:
local laRoute = {
    ["pittsburgh"] = {["modemChannel"] = 10, ["state"] = true},
    ["charlotte"] = {["modemChannel"] = 11, ["state"] = false},
    ["atlanta"] = {["modemChannel"] = 12, ["state"] = true},
    ["stlouis"] = {["modemChannel"] = 13, ["state"] = true},
    ["omaha"] = {["modemChannel"] = 14, ["state"] = false},
    ["denver"] = {["modemChannel"] = 15, ["state"] = false},
    ["boise"] = {["modemChannel"] = 16, ["state"] = true},
    ["sacramento"] = {["modemChannel"] = 17, ["state"] = false},
    }

Ok so its not the best route to take but pretend they are the Winchester brothers

When you select a destination on the server the server will call this table and it will attempt to address each junction in turn using a generic for loop (the for i,v in pairs() do one)

It will use the modemChannel information to make sure that it is calling the right junction and it will instruct the junction to set its redstone output to state. This will work best if you store your destinations in a table (as the key) and have the route tables stored with the relevant key destination. For example

Code:
function setJunction(sendChannel, redstoneState)
 --[[This function will be responsible for sending an instruction to a junction on a particular channel to set its redstone state)
end

local destinations = {
 ["Los Angeles"] = laRoute,
 ["New York"] = nyRoute,
 ["Atlanta"] = atlantaRoute,
 ["Miami"] = miamiRoute,
 ["Houston"] = houstonRoute,
 }

local destination = getDestination() -- a function that somehow gets user input for the destination as a string

for i,v in pairs(destinations[destination]) do -- Iterate through each junction to set it
 print("Setting junction: "..i.." to "..v["state"])
 setJunction(v["modemChannel"], v["state"])
end

I haven't done this myself but I think it should work. I have chosen unique modem channels to make sure you are communicating with the right junction but if you want to limit the number of channels you use then you can use other authentication methods. I often use a unique string that the client and server use to let each other know who they are talking to.

Also, that modem code is pretty ingenious.

Why thank you, but its pretty easy when you get the hang of it. I am doing something a bit crazy right now though. I am writing client/server code for a railcraft elevator where there is a client on each floor and clients automatically register themselves with the server when they start up for the first time (after they have been configured). This updates the floor list on the server and then every other client can be made aware of every floor including the new ones. The aim is that I will be able to do all this without having to restart the server or any existing clients. The client is nearly finished but the server is only about a third of the way done. The actual railcraft control stuff isn't even started yet.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
Very interesting. Unfortunately, it seems my world is corrupt. Which means I had to roll back a couple of days. That said, I'm still going to try your code. Because it's too awesome to waste.

That elevator sounds interesting. My only question is how to get it to stop at each floor. I thought it powered all the way up an elevator track?
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Shame about the world corruption. Glad you like the code though I hope it works in the end

When powered by redstone, elevator tracks power every elevator track below them leaving the ones above unpowered. Having a redstone connection at each level allows you to make sure that the cart only rises and falls as much as you want it. When the code is finished, the client will be the one controlling the redstone at its particular level but it will only do so when ordered to by the server.

As an aside, you can also mount an elevator track directly onto mfr rednet cable which is really cool.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
That is very cool. And it turns out my backup only lost the building I built around the Ars Magicka area and the Pearls. And I have one of the pearls back already.

Didn't know that about elevator tracks. Might have to try them out at some point then.

MFR cable is absolutely awesome. I use it for my computer controlled smeltery.
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
That is very cool. And it turns out my backup only lost the building I built around the Ars Magicka area and the Pearls. And I have one of the pearls back already.

Didn't know that about elevator tracks. Might have to try them out at some point then.

MFR cable is absolutely awesome. I use it for my computer controlled smeltery.
I can't decide if I want to use rednet cable. On the one hand it is really awesome, but on the other hand project red red alloy wire is a multipart. Decisions, decisions

By the way, a computer controlled smeltery! How does that work? It sounds pretty cool
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
Basically, I have a computer sitting on top of the Smeltery, feeding into MFR Rednet Cables. Since the cables are coded 1,2 for white and orange, it outputs white signal for ingots, and orange for blocks. Took me forever to figure out how to get the number from the arguments with the program title.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
Okay, so I finally got a chance to try this out, and it gives me an error when I try to call an os.pullEvent. It says the line is an unfinished string.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
This:
local modem = peripheral.wrap("bottom")
local sendChannel = 10
local replyChannel = 11

while true do
modem.open(sendChannel)
local event = {os.pullEvent("modem_message)}

--[[event table structure
event = {
[1] = string eventDescription, - "modem_message"
[2] = string modem,
[3] = number sendChannel,
[4] = number replyChannel,
[5] = string message,
[6] = number distance,
}
]]

local messageRecieved = event[5]

if messageRecieved == "mining" then
modem.transmit(replyChannel, sendChannel, "Route set Mining")
redstone.setOutput("left", false)
else
if messageRecieved == "ArsMagicka" then
modem.transmit(replyChannel, sendChannel, "Route set Ars Magicka")
redstone.setOutput("left", true)
else
print("Invalid Destination")
end
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
local modem = peripheral.wrap("bottom")
local sendChannel = 10
local replyChannel = 11

while true do
modem.open(sendChannel)
local event = {os.pullEvent("modem_message)} **********

--[[event table structure
event = {
[1] = string eventDescription, - "modem_message"
[2] = string modem,
[3] = number sendChannel,
[4] = number replyChannel,
[5] = string message,
[6] = number distance,
}
]]

local messageRecieved = event[5]

if messageRecieved == "mining" then
modem.transmit(replyChannel, sendChannel, "Route set Mining")
redstone.setOutput("left", false)
else
if messageRecieved == "ArsMagicka" then
modem.transmit(replyChannel, sendChannel, "Route set Ars Magicka")
redstone.setOutput("left", true)
else
print("Invalid Destination")
end


I put some asterisks where the incomplete string is in the spoiler. You forgot to put the speech mark at the end of the "modem_message" string.

Are you still thinking of using the route table thing. I am interested to know how it works.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
Speech mark?

And yes, I intend to set up automated mining out in the ocean, so I'll be setting up a manual rail line, along side a locomotive line. I'll let you know how that goes.
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Speech mark?

And yes, I intend to set up automated mining out in the ocean, so I'll be setting up a manual rail line, along side a locomotive line. I'll let you know how that goes.
Sorry, that must be a British English only thing, I mean one of these ".

The particular line of code should look like this

local event = {os.pullEvent("modem_message")}
With the missing speech mark highlighted

Confusingly, in England we sometimes call them quotation marks and there seems to be no consistency as to whether that refers to ' or ". The differences between the way different English speaking populations refer to these little details has a neverending capability to trip people up :)
 

Arkandos

New Member
Jul 29, 2019
349
0
0
Woo! Go Modem api!
(Although the modem is just a peripheral and not an api. Still love it more than rednet)
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
Ah. Apostrophe is the single, quotation is the double. At least that's how I learned it.

That explains the problem then. One of those blindingly obvious things you don't see yourself.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
@Arkandon: There's actually a Modem API as well as a Modem Peripheral.

@casilleroatr: That was the problem. Actually needed a couple more ends, but now I can switch the track by remote. Thanks for the help. Now to get the resources to build the next part and try out the code for multiple routings.