You should now have a turtle that mines cobblestone from an infinite cobblestone generator and drops the cobblestone into furnaces to smelt stone. You’ve automated the smelting process, but you still have to manually take the stone from the furnaces to use it. That’s useful, but it’s not exactly what we would call a stone brick factory. Now you need to program a second turtle to pull out the smelted stone and craft stone bricks. Once you have your turtle team running, like in Figure 10-1, you’ll have all the stone bricks you need to build with.
Figure 10-1: The complete setup for an automated stone brick factory
The first turtle, running the cobminer program, is positioned above the furnaces. The second turtle will move beneath the furnaces so it can pull items from each furnace’s output slot. Remember that mining stone or cobblestone blocks produces cobblestone blocks. Putting these cobblestone blocks into a furnace will produce stone blocks, and stone blocks can be used to craft stone brick blocks.
As in the cobminer program, the second turtle’s program first needs to check that the turtle has enough fuel to move across the furnaces and back to its original position. As the turtle moves to each furnace, it gathers stone blocks that have been smelted from the cobblestone. When it has gathered a full stack of 64 stone blocks, it crafts them into 64 stone bricks, which it places in a chest. If there isn’t enough stone in the furnaces’ output slots, the turtle waits two minutes for more cobblestone to be smelted. Then the turtle repeats the entire process.
To make a turtle that can create stone bricks, you first need to make a turtle that can craft. Turtles can craft items with the turtle.craft() function. However, to enable this function, the turtle must equip a crafting table the same way it equips a diamond pickaxe. Choose a turtle other than the one running the cobminer program and place a crafting table in the turtle’s currently selected slot. Then run the following code in the Lua shell:
lua> turtle.equipLeft()
This code will unequip any tool on the turtle’s left side and equip the crafting table in the currently selected slot. Figure 10-2 shows the turtle and its inventory before and after running turtle.equipLeft().
Figure 10-2: The turtle before (left) and after (right) calling turtle.equipLeft() to unequip the pickaxe and equip the crafting table
Now you can have your turtle call the turtle.craft() function. Your pickaxe-less turtle won’t be able to call turtle.dig(), but this stone brick–making turtle doesn’t need to mine anything.
NOTE
If you want a turtle that can craft and dig, you can equip a turtle with two tools. You do this by calling both turtle.equipLeft() to equip one tool on the left side of the turtle and turtle.equipRight() to equip another tool on the right side. Figure 10-3 shows a turtle with a diamond pickaxe on the left side and a crafting table on the right, letting the turtle call both turtle.dig() and turtle.craft().
Figure 10-3: A turtle with a diamond pickaxe on its left side (left) and a crafting table on its right side (right)
With the crafting table equipped, the turtle can craft items in its inventory using the same recipe layouts as a crafting table. When the turtle calls turtle.craft(), the crafted item will be placed in the currently selected slot. For example, to craft stone bricks, lay out four stone blocks in a square in the turtle’s inventory, as shown in Figure 10-4. Make sure all the other inventory slots are empty, and run turtle.select(16) and turtle.craft() from the Lua shell:
lua> turtle.select(16)
true
lua> turtle.craft()
true
Figure 10-4 shows the turtle’s GUI before and after crafting stone bricks. Notice that inventory slot 16 is currently selected in the figure, and the crafted item is placed in the currently selected slot.
Figure 10-4: The turtle’s inventory before (left) and after (right) calling the turtle.craft() function
If the items you lay out don’t match any Minecraft recipe, turtle.craft() will return false and you’ll see this error message:
lua> turtle.craft()
false
No matching recipes
Now that we’ve done all the setup and planning for the second turtle’s program, let’s write the code. We’ll call the second turtle’s program brickcrafter.
From the command shell, run edit brickcrafter and enter the following code:
brickcrafter
1. --[[Stone Brick Factory program by Al Sweigart
2. Gets stone from furnace to craft stone bricks, turtle 2 of 2]]
3.
4. print('Starting stone brick crafting program...')
5.
6. local NUM_FURNACES = 5
7. local brickCount = 0
8. while true do
9. -- check turtle's fuel
10. if turtle.getFuelLevel() < (2 * NUM_FURNACES) then
11. error('Turtle needs more fuel!')
12. end
13.
14. turtle.select(1) -- put stone in slot 1
15.
16. -- start collecting stone from furnaces
17. for i = 1, NUM_FURNACES do
18. turtle.suckUp(64 - turtle.getItemCount(1)) -- get stone from furnace
19. if turtle.getItemCount(1) == 64 then
20. break -- stop once there are 64 stone blocks
21. end
22. if i ~= NUM_FURNACES then
23. turtle.back() -- move to next furnace
24. end
25. end
26.
27. -- craft stone bricks
28. if turtle.getItemCount(1) == 64 then
29. turtle.transferTo(2, 16) -- put in slot 2
30. turtle.transferTo(5, 16) -- put in slot 5
31. turtle.transferTo(6, 16) -- put in slot 6
32. turtle.select(16) -- stone bricks to go in slot 16
33. turtle.craft() -- craft stone bricks
34. brickCount = brickCount + 64
35. print('Total stone bricks: ' .. brickCount)
36. else
37. print('Not enough stone yet. Sleeping...')
38. os.sleep(120) -- wait for 2 minutes
39. end
40.
41. -- move back to chest (by first furnace)
42. for i = 1, NUM_FURNACES - 1 do
43. turtle.forward()
44. end
45. turtle.turnLeft() -- face chest
46. turtle.select(16) -- select stone bricks
47. turtle.drop() -- put stone bricks into chest
48. turtle.turnRight() -- face generator again
49. end
After you’ve entered all of these instructions, press the CTRL button, make sure [Save] is selected, and press ENTER. Then quit the editor by pressing CTRL, selecting [Exit], and then pressing ENTER.
Before you can run the brickcrafter program, you’ll need to have a turtle that is running the cobminer program with the cobblestone generator and furnace setup from Chapter 9. You’ll also need a second chest (single- or double-size) and a second turtle to run the brickcrafter program. Place the new chest next to the cobblestone generator and position the new turtle under the first furnace, as shown in Figure 10-5. The chest will hold all of the crafted stone bricks. Make sure your turtle’s inventory is completely empty, or the brickcrafter program won’t run as expected.
Figure 10-5: The position of the chest and turtle. The white arrow shows which direction the turtle should face. The dotted lines show where the furnaces are positioned on the second layer of the cobblestone generator.
The complete setup for your cobblestone generator and stone brick crafter will look like Figure 10-6.
Figure 10-6: Put a chest next to the cobblestone generator to provide storage for the stone bricks.
This brickcrafter program instructs the turtle to move underneath the furnaces and take out each furnace’s smelted stone. Then the turtle lays out the stone blocks according to the stone brick recipe, calls turtle.craft() to create stone bricks, and places the stone bricks into the chest next to the generator. Because the turtle must move back and forth, it will check its fuel level and stop the program if it runs out of fuel.
If you get errors when running this program, carefully compare your code to the code in this book to find any typos. If you still cannot fix your program, delete the file by running delete brickcrafter and then download it by running pastebin get 1zS07K3U brickcrafter.
The first few lines of the program contain the usual descriptive comments and a print() call that displays a message telling the player the program has started. We also set up two variables we’ll use later in the program.
brickcrafter
1. --[[Stone Brick Factory program by Al Sweigart
2. Gets stone from furnace to craft stone bricks, turtle 2 of 2]]
3.
4. print('Starting stone brick crafting program...')
5.
6. local NUM_FURNACES = 5
7. local brickCount = 0
The NUM_FURNACES constant serves the same purpose as the NUM_FURNACES constant in the cobminer program from Chapter 9. The brickCount variable keeps track of the number of stone bricks the turtle has crafted.
Line 8 begins an infinite loop for the main part of the program. The program continues running until the turtle runs out of fuel or the player presses CTRL-T to terminate the program.
brickcrafter
8. while true do
9. -- check turtle's fuel
10. if turtle.getFuelLevel() < (2 * NUM_FURNACES) then
11. error('Turtle needs more fuel!')
12. end
Inside the loop, the program first checks that the turtle has enough fuel to reach each furnace and return to the chest. Lines 10 to 12 are similar to lines 23 to 25 in the cobminer program in Chapter 9. Line 10 checks that the turtle has at least twice as much fuel as the number of furnaces. If not, the call to error() on line 11 terminates the program.
If the turtle has enough fuel to move under all the furnaces and back, it selects inventory slot 1 so that when it takes the stone from a furnace, the stone ends up in this slot.
brickcrafter
14. turtle.select(1) -- put stone in slot 1
Next, the execution enters a for loop on line 17. On each iteration of the loop, the turtle pulls out smelted stone from the furnace above it to fill up inventory slot 1. When the turtle has filled its inventory slot to maximum capacity (64 blocks), it breaks out of the loop so it can then craft stone bricks from the stone. If inventory slot 1 is not yet full, the program execution continues to the next if statement and moves the turtle backward to the next furnace.
brickcrafter
16. -- start collecting stone from furnaces
17. for i = 1, NUM_FURNACES do
18. turtle.suckUp(64 - turtle.getItemCount(1)) -- get stone from furnace
19. if turtle.getItemCount(1) == 64 then
20. break -- stop once there are 64 stone blocks
21. end
22. if i ~= NUM_FURNACES then
23. turtle.back() -- move to next furnace
24. end
25. end
The turtle.suckUp() function takes all the blocks from a container above a turtle and stores them in the turtle’s currently selected slot. You can pass this function a number to limit the amount of blocks sucked into the turtle’s selected slot. You can also use the turtle.suck() and turtle.suckDown() functions to take blocks from containers in front of and below the turtle, respectively.
In this case, because the turtle is under the furnaces, it pulls out items from the furnace’s output slot. The turtle can hold a maximum of 64 stone blocks in inventory slot 1, so we do some math to ensure that the turtle doesn’t try to overfill its slot. The turtle.getItemCount(1) part of the command returns the number of blocks the turtle already has in its slot, which we subtract from 64 to get the number of blocks the turtle should retrieve from the furnace. For example, if inventory slot 1 already has 30 stone blocks in it and there are 64 stone blocks in the furnace, the turtle shouldn’t take out all 64 stone blocks. Instead, it should take out no more than 64 – 30, or 34, stone blocks.
If the number of items in inventory slot 1 is 64, then we don’t want to add more blocks to the slot. The if statement on line 19 evaluates to true, and the execution breaks out of this for loop.
If the inventory slot is not yet full, the turtle needs to move backward to go under the next furnace. The turtle should continue pulling items from the furnace it’s beneath and then move to the next furnace until it’s under the last furnace. The turtle is under the last furnace when i, the for loop’s variable, is set to the same number as NUM_FURNACES. This is why the if statement on line 22 only runs line 23 if i doesn’t equal NUM_FURNACES. When the turtle reaches the last furnace, it exits the for loop.
When the turtle has 64 stone blocks, it needs to craft them into stone bricks. Remember that turtles craft stone bricks using the same recipe as you would use on a crafting table, but instead the turtle crafts stone bricks in its own inventory. To craft stone blocks into stone bricks, put equal amounts of stone blocks into four inventory slots to form a square. Figure 10-7 shows the recipe to craft stone bricks.
Figure 10-7: The recipe for crafting stone bricks (left) and the same recipe in the turtle’s inventory (right)
When the stone blocks are in the correct recipe pattern, calling turtle.craft() will craft as many stone bricks as possible and store them in the current slot. If you want the turtle to craft only a certain number of items, even if it has enough material for more, pass a number argument to turtle.craft(). For example, turtle.craft(1) will use only one stone block from each slot and craft a single stone brick.
Line 28 checks if there are 64 stone blocks in inventory slot 1. If there are, the execution enters the code block starting on line 29.
brickcrafter
27. -- craft stone bricks
28. if turtle.getItemCount(1) == 64 then
29. turtle.transferTo(2, 16) -- put in slot 2
30. turtle.transferTo(5, 16) -- put in slot 5
31. turtle.transferTo(6, 16) -- put in slot 6
32. turtle.select(16) -- stone bricks to go in slot 16
33. turtle.craft() -- craft stone bricks
34. brickCount = brickCount + 64
35. print('Total stone bricks: ' .. brickCount)
The turtle.transferTo() function moves items from the current slot to another slot. You can specify which slot the items are moved to by passing an integer as the first parameter of the function, and you can specify the number of items that are moved to the slot with the second parameter. The turtle.transferTo(2, 16) function call on line 29 moves 16 stone blocks from the current slot (which is 1, as set on line 14) to slot 2.
Lines 30 and 31 move 16 stone blocks to slots 5 and 6, which results in the turtle’s inventory looking like the recipe in Figure 10-7. Then, line 32 calls turtle.select(16) to change the current slot to slot 16 so when turtle.craft() is called on line 33, the crafted stone bricks will be placed in slot 16. Lines 34 and 35 calculate and print the number of stone bricks crafted by the turtle so far.
If the turtle didn’t have 64 stone blocks in inventory slot 1 after pulling them from the furnaces, line 38 pauses for 120 seconds (two minutes) to give the furnaces more time to smelt stone blocks.
brickcrafter
36. else
37. print('Not enough stone yet. Sleeping...')
38. os.sleep(120) -- wait for 2 minutes
39. end
In this case, the program would continue and the turtle would move back to the first furnace. Whether or not stone bricks have been crafted, the turtle needs to move back to the first furnace next to the cobblestone generator so it can collect more smelted stone.
To move the turtle back to its original position, we need to move the turtle forward until it arrives at the first furnace again, which we do on line 42 with a for loop. Once there, the turtle stores its stone bricks in the chest.
brickcrafter
41. -- move back to chest (by first furnace)
42. for i = 1, NUM_FURNACES - 1 do
43. turtle.forward()
44. end
45. turtle.turnLeft() -- face chest
46. turtle.select(16) -- select stone bricks
47. turtle.drop() -- put stone bricks into chest
48. turtle.turnRight() -- face generator again
49. end
Lines 42 to 44 move the turtle forward so that it’s back in its original position. That is, the turtle moves NUM_FURNACES – 1 so that it’s below the first furnace. On line 6, we set NUM_FURNACES to 5, so the turtle moves four spaces here. Line 45 turns the turtle to face the chest and line 46 selects all the stone bricks it crafted, which are in inventory slot 16. Then line 47 puts the selected stone bricks into the chest (or does nothing, if no bricks were crafted), and line 48 turns the turtle right to face the cobblestone generator again.
The end statement on line 49 corresponds with the infinite while loop that began on line 8, so when the execution reaches this point, it jumps back to line 8 to begin the entire process of collecting stone, crafting it into stone bricks, and dropping the stone bricks into the chest all over again.
The cobblestone generator and turtles are the main part of your factory line, but they’re currently outside, where they’re exposed to the rain and creepers. You’re still missing your factory building! Now that you have an unlimited source of cobblestone and crafted stone bricks, you can create a building to house your cobblestone generators, as shown in Figures 10-9 and 10-10.
Figure 10-9: A building to house the cobblestone generator and turtles, made from the products of the cobblestone generator
Figure 10-10: The interior, with two cobblestone generators and a decorative lava waterfall
Fairly soon, your turtles will have produced plenty of stone bricks with which to build, as shown in Figure 10-11.
Figure 10-11: Your stone brick supply problems are over, thanks to the power of programming!
Creating a building for your cobblestone generator is optional, but at least you won’t have to mine the blocks for it yourself if you do decide to build it. And in Chapters 11 and 12, you’ll learn how to program the turtles to build walls and rooms for you!
In this chapter, you learned how to swap out tools and equip a crafting table using the turtle.equipLeft() and turtle.equipRight() functions. Equipping a crafting table makes the turtle.craft() function available to the turtle.
To take items out of containers like chests or furnaces, you use the turtle.suck() function. You can pass a number argument to this function to control the number of items that are taken, and you can call turtle.suckUp() or turtle.suckDown() to interact with containers above or below the turtle.
Before calling turtle.craft(), you need to arrange items in the turtle’s inventory according to recipes, just as the items would be arranged on a crafting table. You can use turtle.transferTo() to move items to different inventory slots to accomplish this. After calling turtle.craft(), the crafted items will appear in the currently selected slot.
With all the stone bricks we have now, let’s start programming turtles to construct giant buildings for us in Chapter 11!