Railcraft Item Depot with some computercraft stuff

  • 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

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
I have been going heavily into railcraft recently and have tasked myself with building the perfect train yard. That will probably never happen because I am not the best builder but I have been doing a couple of things recently which I thought were good enough to share with the community. Please bear in mind that this is a work in progress so and some of the programs are not very good (might be difficult to install properly in a new similar set up). Also I play in creative so I have been quite liberal with resource use. There might be more frugal ways of doing this. Also the forums don't handle picture uploads very well.

I have written this up with pictures on imgur as well,

http://imgur.com/a/233eN

If you don't mind reading the wall of text below, I try to explain a cool system that unloads long trains at the same time, and measures and records the items that get unloaded.

Uses:

Railcraft
Computercraft
Open peripherals
Translocators
Buildcraft
Minefactory Reloaded

Computer controlled item depot

When a train pulls up the first thing it does is go over a line of train detectors set up to emit redstone on trains of different lengths, from 3 to 7. Trains can consist of a locomotive at the front, anywhere between 1 and 5 chest carts in the middle and an anchor cart at the end. The train detectors are hooked up with rednet cable to a computer and the computer waits for a redstone event. Depending on the length of the train, the computer receives a different coloured signal so it knows how long the train is. This will be important later.

Meanwhile the train also passes a routing detector. I will skip over that for now.

After going round a short loop the train hits a holding track and the chest carts line up next to some advanced item unloaders. I used advanced because it allowed me to make a cleaner build but normal ones will work the same. The tracks were laid on top of item detectors that were each lined up just the same as the unloaders so each chest cart was being acted on by one detector and one unloader. The unloaders detected empty chest carts.

The detectors were hooked up to the same computer that i mentioned earlier (that measures the train length) using rednet cable. It is important that each detector is on a different colour.

The computer is also controlling the holding track for the locomotive. When it detects that all chest carts are empty it lets the locomotive go. It needed to test for the train length for two reasons. It is a practical way of letting the computer know that a train has arrived and it needs to start doing its thing, and also it needs to know how many signals from the item detectors it needs to AND together to let the train go. My program can support a train with between 1-5 chest carts and a loco and anchor at wither end. Meanwhile, the unloaders deposit the items into iron chests and they are then quickly piped out using diamond autarchic gates (for speed) into a pair of diamond chests. Those diamond chests are wrapped to another computer as peripherals. The same computer also needs a wireless modem and a printer. I managed to upload this picture to demonstrate. (Ignore the logistics pipes they aren't doing anything).

2013-11-16_03.19.33.png

That computer is also connected to a large mfr rednet network (including a controller). That network is kept seperate from the one that the other computer was using with the detectors. This picture will hopefully show you that there are two seperate rednet networks.

2013-11-16_03.21.58.png

When the locomotive leaves the holding track it immediately passes a detector which triggers the second computer into action. The second computer immediately sends out a redstone signal which is inverted by a rednet controller to turn off another holding track stopping the locomotive. It is only temporary (just while the computer finishes its short job to - it is a preventative measure coupled with some signalling to make sure I don't have loads of trains arriving at once).

Then the computer sleeps for a bit to allow all the items to fill up the diamond chests. Using open peripherals I could iterate through each slot in the chests and get the name and amount of the items within. This data is compiled into a large table. When two slots are occupied by the same item, e.g there is 64 iron ore in slot 1 and slot 2, the contents of each slot are added together. Then, using a printer I print out that information and record the time and date. I also give the inventory a unique key (not important it was just for fun). The last component of the book is sorted out by the routing detector.

Right now I only have one routing detector but I plan on having more, one for each train I have going through this depot. The train I have set up is meant to carry ores to the facility for processing. It is given a ticket which says

Dest=CloudyMountainItemDepot/Ores

Every train that goes through here will have the CloudyMountainItemDepot bit on there ticket but the bit after the dash gives some info about what they are carrying. I have a routing table inside the detector which matches the ticket and when a matching train goes past it outputs a redstone signal which is measured by a pair of computers. I have used a pair of them because of the way I chose to record it (it is probably not the best way, but it works well enough). The first stores a redstone signal based on which detector gets fired. It will only change its output if it gets a reset command or if its redstone input changes and it the input is nonzero (to get around the fact that the detectors only pulse). The second computer takes that redstone signal and uses it to decide what the cargo is. In this case it sets the trains cargo id to "Raw ore delivery". It stores that information until it is requested by the printer computer, at which point it starts again and commands the detector computer to refresh as well.

Then the whole book gets printed (I haven't automated crafting the books yet or removing stuff from the printer, but you can do that however you want). The computer sends out a redstone signal that triggers a translocator to empty the diamond chests into the sorting system and it waits until the chests are empty. I have used buildcraft gates to emit redstone when the chests are empty. The signals from the two gates are anded by the rednet controller and when both chests are empty the train is properly released and the system resets.

I then get a nice book like this

2013-11-16_04.30.57.png


It has a title. CMD stands for cloudy mountain depot and the code is the unique identifier.

2013-11-16_04.30.43.png


2013-11-16_04.30.44.png


As an aside, I used two different types of copper ore when I ran this test and it added the amounts together properly inside the same entry!

Finally, some item names are too long to fit onto a line on the page so I took a special measure against that should a name be too long

2013-11-16_04.44.32.png

I just need to test my computer programs properly and then I will post pastebin links for them should any of you wish to use them. I will also put together an imgur album to explain it a bit better.

EDIT: OK I have tested my programs and they all work fine together (or at least I hope they do). I will include the pastebins below for each of the four computers I have used. They should work but the set up might be a bit tricky. I haven't designed them to be extremely user friendly because I did not expect to put them up one day. However it shouldn'y be too difficult if you use the pictures from the upcoming imgur album to help, especially if you can read the code.

Cargo Taker = [url]http://pastebin.com/j78rdihh[/URL]

Important EDIT: About 10 minutes ago I realised I forgot to take a break out that I was using during testing. I missed it because I am a derp. I don't think anyone has downloaded this yet but if you have, either get the new version using the new code or go to line 253 and remove the word break. Sorry.

This computer is the one that reads the chest inventories and prints the contents out. It also uses a wireless modem. I have written it so that the chests are on the top and right, the printer is on the left, the modem is on the bottom and the rednet cable is on the back. You will have to change the code manually if you want to put the peripherals on different sides (the same goes for the other programs).

Routing Redstone Reader = 2ssAtrkn

This computer is connected via rednet cable on the top to a line of routing detectors and on the right it has a rednet connection to the Train Identifier computer. There is also a modem on the back.

Train Identifier = Q71RjLat

Uses the signal put out by Routing redstone reader to name the cargo. Rednet connection on the left, modem on the back.

Unloader Manager = 6g4Aw0DT

Seperate from the inventory scanning network, this computer makes sure that the whole train gets completely emptied before sending it off. This can function independantly of the other three programs. Rednet cable goes on the bottom, the lockdown track must be placed on top of the computer.

The imgur album will probably come tomorrow.
 
Last edited:

Robert Mack

New Member
Jul 29, 2019
14
0
0
I haven't looked at the code yet, but this sounds a lot like what I have been working on as well. I have some of the code written, but wanted to set up the entire station first. My main station will include incoming freight from the mining operation as well as the slaughter house, prairie farms and logging operations. Looking forward to seeing the album. Are you planning on recording a video for YouTube?
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Thanks for the interest.

I am a bit late in making the album. I am trying to shift my sleeping pattern at the moment so I haven't got round to making the album yet.

I would like to make a video for youtube but I wouldn't really know how. I have no recording software. I would be happy to get a free/trial version to make a video but I wouldn't want to pay for one. I also don't have a microphone. If you could recommend some recording software that I could get for free I would consider making a video. I have already thought of a nice way of speaking to the audience without needing a microphone.
 

Robert Mack

New Member
Jul 29, 2019
14
0
0
I don't have any recommendations for you as far as a GOOD free software. What I may be able to do is build my setup with your code and do a YouTube video and link this convo and your pastebin code and give you the credit.
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
I would be happy with that if you wanted to make the video. Make sure to give me the link I would be keen to watch the video. Credit would be appreciated where its due as well.

Be sure to wait for the album though. I have taken detailed screenshots and hopefully it will properly explain how to put the thing together. (Thats not to say you can't make adjustments in your video to suit you :)).
I took all the screenshots this morning and I am putting the album up soon.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
Bandicam records Minecraft pretty well. The free version is limited to ten minutes and leaves a watermark, but other than that it's perfectly fine.

How did you get stuff to wrap? I was trying to build a base monitoring system, but I couldn't get the data from some tanks to print out so I could read the table and pull out the variable I wanted.
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Bandicam records Minecraft pretty well. The free version is limited to ten minutes and leaves a watermark, but other than that it's perfectly fine.

How did you get stuff to wrap? I was trying to build a base monitoring system, but I couldn't get the data from some tanks to print out so I could read the table and pull out the variable I wanted.

Reading some of the tables that you get from open peripherals can be a bit funny. It took me a lot of experimenting. In the same depot that this item thing is I have 4 steel tanks that are set up to contain oil, fuel, crushed ice and liquid force. I wrote another program that displayed data about the 4 tanks to a screen which could be refreshed if you click it (I took some pictures of it that are going in the album soon). To get the data I hooked up each of the four tanks to a computer using wired modems. When you click to activate the modem you get a chat message which shows the name of the peripheral (btw to read railcraft tanks you need to put the modem on a valve), for exampe "steel_tank_valve_0". I used a for loop to iterate 0 through 3 to make a table of strings "steel_tank_valve_"..i to get the names of all the tanks. Then I made another table using a for loop using this code

Code:
local side = {}
local tank = {}

for i = 1,4 do
    local t = "steel_tank_valve_"..i-1
    side[i] = t
    tank[i] = peripheral.wrap(t)
end

then I could refer to tank 3 using tank[3].

I wrote another function called getTankData() here

Code:
function getTankData(name, key)
    local tankData = {}
    tankData = tank[key].getTanks(side[key]) --[[this is the open peripheral command which reads tank data. You need to give it the side (or name if using wired modems like I did) that the tank is on, even though you wrapped                                                                        the peripheral. I have no idea why. It returns this huge nested table (I think it is so nested so that it can support blocks that have 2 tanks in them like combustion engines).]]
   --[[*****look here*****]] local capacity = tankData[1]["capacity"] -- Try iterating through tankData[1] on a tank using for i,v in pairs(tankData[1]) do print(i..": "..v) end. The keys inside that table are strings like "capacity"
    local amount = nil
    if tankData[1]["name"] ~= nil and tankData[1]["name"] ~= name then -- this stuff here is just me constructing a simpler table.
        name = tankData[1]["name"]
        print("Tank/Title Mismatch. Manual Check Required")
    end
    if tankData[1]["amount"] == nil then
        amount = 0
    else
        amount = tankData[1]["amount"]
    end
    local fill = round((amount/capacity*100),2).."%"
    local data = {
        [1] = name,
        [2] = amount,
        [3] = capacity,
        [4] = fill,
    }
    return data -- Data is a much simpler table that you can iterate through with one generic for loop without having to nest a load of them within each other.
end

the parameter key is what allows me to select the right variable from the table earlier. If you wrap your tank peripherals in a table too then this function should work for you too. If you want to write your own function, or get the rest of the data about the table, then like I said, just read from tankData[1].

Here is the whole code for the tank monitor I wrote if you want to look at it

Code:
--Tank Analyser

local mon = peripheral.wrap("monitor_1")
local x,y = mon.getSize()
local tank = {}
local side = {}
local tankNames = {
    [1] = "Fuel",
    [2] = "Oil",
    [3] = "Crushed Ice",
    [4] = "Liquid Force",
    }

for i = 1,4 do
    local t = "steel_tank_valve_"..i-1
    side[i] = t
    tank[i] = peripheral.wrap(t)
end

function round(x,y)
    local f = 10^y
    local r = math.floor(x*f+0.5)/f
    return r
end

function getTankData(name, key)
    local tankData = {}
    tankData = tank[key].getTanks(side[key])
    local capacity = tankData[1]["capacity"]
    local amount = nil
    if tankData[1]["name"] ~= nil and tankData[1]["name"] ~= name then
        name = tankData[1]["name"]
        print("Tank/Title Mismatch. Manual Check Required")
    end
    if tankData[1]["amount"] == nil then
        amount = 0
    else
        amount = tankData[1]["amount"]
    end
    local fill = round((amount/capacity*100),2).."%"
    local data = {
        [1] = name,
        [2] = amount,
        [3] = capacity,
        [4] = fill,
    }
    return data
end

function title()
    local str = "Liquid Storage Monitor"
    local len = string.len(str)
    local pos = math.ceil((x/2)-(len/2))
    mon.setCursorPos(pos,2)
    mon.write(str)
end

while true do
    term.clear()
    term.setCursorPos(1,1)
    print("Liquid Storage Monitor -- Controller")
    print("Click the monitor to refresh tank levels.")
    mon.clear()
    title()
    mon.setCursorPos(1,1)
    for i = 1,4 do
        local cats = {"Type", "Quantity", "Capacity", "Fill"}
        local tankData = getTankData(tankNames[i], i)
        local n = x/4
        local point = 2+((i*n)-n)
        mon.setCursorPos(point,5)
        for i = 1,4 do
            local cX, cY = mon.getCursorPos()
            local str = cats[i]..": "..tankData[i]
            mon.write(str)
            local add = 1
            if i == 1 then
                add = 2
            end
            mon.setCursorPos(point, add+cY)
        end
    end
    mon.setCursorPos(1,y)
    mon.write("Click monitor to refresh tank levels")
    os.pullEvent("monitor_touch")
    print("Resetting")
end

Or were you asking about the chests?
 
  • Like
Reactions: KingTriaxx

Flipz

New Member
Jul 29, 2019
669
0
0
I use BBFlashBack Express for my recording needs--but do note that YT vids require both a recording program AND editing software, which is where I get stuck. :/
 

Redius

New Member
Jul 29, 2019
222
0
1
I use BBFlashBack Express for my recording needs--but do note that YT vids require both a recording program AND editing software, which is where I get stuck. :/

I just started using DXtory (for the love of god, download the x264 codec, or your vids will be enormous...to the tune of 1gb for 1min of recording!), and love it. It's easy to manage, and with the x264 codec, you get amazing compression and solid frames. I got a 15minute recording for under 1GB worth of space...and it recorded in 1080p!
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Thanks for the video recording advice everyone. I'm not sure if I will make decent videos though. However, the picture album is nearly done!
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
I meant about the special measure you took to ensure names that were too long fit.

That other thing is awesome. It's also a bit over my head, but I'll see what I can do with it. Thanks for posting it.
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
Update: I have finished uploading images to to imgur and giving them nice captions. The album is now public.
Here is a link

http://imgur.com/a/233eN

I meant about the special measure you took to ensure names that were too long fit.

That other thing is awesome. It's also a bit over my head, but I'll see what I can do with it. Thanks for posting it.

Oh I see. Its just because you mentioned tanks and I thought you were looking for generic open peripherals questions. However, I can help you in your other question too.

Lets say you have a long string for example (I will label it str) str = "Programmable rednet controller" (30 characters long). I happen to know that the length of a line on printed paper is 25, but the method I am about to show you will work (possibly with small adjustments) for any sized line. So, str is too long to fit on that line.
When I was iterating through the inventory table that contained the name and quantity of each item to print it onto paper I ran this conditional (I have added comments)

Code:
    local x = 25 -- this was defined earlier. The page.getSize function doesn't work until you have actually started a page which is annoying so I hard coded the value in.
   --[[
     some code that doesn't need to be shown here 
     ]]
    local strLength = string.len(str)
    if strLength > x then
            local aX, aY = printer.getCursorPos() -- I am mainly interested in aY here.
            local linesRequired = math.ceil(strLength/x) -- this calculation works out how many lines will be needed to print out the whole string
            print("Lines: "..linesRequired)
            print("Page Remaining: "..y-aY)
            if y - aY < linesRequired then -- I check if the string can't fit on the page here. If it can't then I just start a new page.
                printer.endPage()
                printer.newPage()
                printer.setPageTitle(id) -- Don't worry about this command it was just the thing to make sure that each page in the book had the same id. It is not necessary and was part of the 'just for lolz' aspects of my program
                printer.setCursorPos(1,1)
            end
            longPrint(str) -- longPrint(str) is a function that I made which I will show below
        else
            printer.write(str) -- If the string will fit on a single line then doing just this is absolutely fine.
        end

So the check itself is pretty simple, lets get to how I printed it.
It relies on the command, string.gmatch(str, pattern) to work. It will iterate through str and return all examples of what you specify in the pattern. The pattern is a string. You can specify the command to look for specific letters or sequences of letters like this "st". There are certain "magic" characters as well which can find certain types of character. There is a pattern that returns only digits, only letters, lower case only and more. A single full stop (or period for Americans) represents any character

Code:
-- it is a pretty short function and it is pretty simple when you break it down (I got the information on the lua website)
function longPrint(str)
    print("LongPrint - "..str) -- This is just a console print that I used for testing
    local x,y = printer.getPageSize() -- Gets the size of the page. Now I am mainly interested in x. This is one of the areas that may need tweaking for your purposes.
    for i in string.gmatch(str, ".") do -- sets up the iterations. You can end up printing each character in turn using the variable i
        local cX, cY = printer.getCursorPos() -- Keeps track of where you are on the page
        if cX > x then -- When the program detects that it is at the end of the line, it starts a new line before printing the character
            newLine() -- I had to make my own newLine function because \n doesn't seem to work on the printer.
        end
        printer.write(i) -- and then you just need to print the character which is stored in the i variable.
    end
end

This function was written specifically for the printer but once you understand the string.gmatch function it is trivial to adapt it to other lines, for example a monitor or even a segment of a monitor. However, if I explained string.gmatch terribly then you can look at this link. http://www.lua.org/manual/5.2/manual.html#6.4. It also gives a full list of all the patterns which is very useful. In my opinion though, the formatting of the pattern section could be better. I got very confused when going through it because they put colons everywhere for some reason. Ignore the colons - they are not part of the pattern.

If you are printing to a monitor and you want to start a new line after a certain point, it would be a good idea to store the starting cursor position of the string and for each character ensure that the new current position is less than the starting position plus the length of the line.
 
  • Like
Reactions: mikrosenshi

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
That's genius. I was looking for the OpenPeripherals information, but I love coding tricks like this. I'm definitely going to give this a try.
 

Robert Mack

New Member
Jul 29, 2019
14
0
0
I am still working on implementing this into my legit single player world for recording. I should have something up by Sunday. Any chance you can upload the world file and let me know what mod pack you are using? That way I can record both settings and make sure I have the setup correct.

Thanks
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
I am a bit reluctant to release a world file for 2 reasons. First, I am using a custom mod pack with completely made up configs so sharing the pack would be difficult. But more importantly, there are other things on that map that are no where near finished and when they are done I am planning on making a few more posts like this one to show whats going on.

If you have any questions about the set up though I will be happy to answer them. I will be happy to look at screenshots of your set up if you feel like that would help too.

A small warning as well. Now I am thinking about it the pastebin for one of my programs may be out of date. It is the one that handles the receipt making. If you have tested it, you may have noticed that it displays the trains type as unknown even though it should know what type of train it is. If I recall correctly, I fixed this simply by changing the location of one line of code. I fixed it on my own map and I can update the pastebin later if need be.
 

KingTriaxx

Forum Addict
Jul 27, 2013
4,266
1,333
184
Michigan
Isn't there a program that lets you copy paste parts of the world? You could always make a new world and copy it there. Then he's got the train station he needs without the rest of the private stuff. Mod pack is still an issue, but you can always find one close enough.
 

Robert Mack

New Member
Jul 29, 2019
14
0
0
A small warning as well. Now I am thinking about it the pastebin for one of my programs may be out of date. It is the one that handles the receipt making. If you have tested it, you may have noticed that it displays the trains type as unknown even though it should know what type of train it is. If I recall correctly, I fixed this simply by changing the location of one line of code. I fixed it on my own map and I can update the pastebin later if need be.

Can you tell me what to fix or update the pastebin. This is the last thing I have to finish in order to record the video.

Thanks.
 

Robert Mack

New Member
Jul 29, 2019
14
0
0
When I give you credit in the video, how do I pronounce your name? Also, do you have anything you want me to share (minecraft name, twiter feed, etc.)?
 

casilleroatr

New Member
Jul 29, 2019
1,360
0
0
My name is pronounced like Cas-ee-air-ro (its not my real name or anything so I don't mind if you mispronounce it :)). My minecraft name is the same as my ftb forum name but without the atr at the end. The only thing I would like credit wise is for a link to this forum thread page saying that the pastebin codes are here too and it would be nice if you said that I write the code. If there is any other credit due I won't complain. I look forward to seeing how you did it. Was it all in survival mode by the way?

Have you needed to edit the code to get it working by the way. Not that I mind, I'm just interested.