My first big program - Branch Mining (safely)
Description
EDIT: Updated 12/11/2019 - Turtles just started misplacing torches on themselves instead of the floor. Added a small fix to the code.Hey everybody,I'd like to share my first somewhat ambitious mining ...
Installation
Copy one of these commands into your ComputerCraft terminal:
Pastebin:
pastebin get XYMvEYDB my_first_big_program_-_branch_mining_(safely)wget:
wget https://pastebin.com/raw/XYMvEYDB my_first_big_program_-_branch_mining_(safely)Archive:
wget https://cc.shobie.xyz/cc/get/pb-XYMvEYDB my_first_big_program_-_branch_mining_(safely)
Quick Install:
wget https://cc.shobie.xyz/cc/get/pb-XYMvEYDB My first big program - Branch Mining (safely)
Usage
Run the program after downloading
Tags
Source
View Original SourceCode Preview
--[[
This program is designed to create a SAFE branch mine with 3x3 hallways, with multiple turtles working in tandem. The turtles will seal off any holes in the walls and will light the mine as they dig it, ensuring that no mobs get into your mine! They will also seal off any lava or water so your mine does not flood [see note 1]. Each turtle is responsible for either a branch or the main trunk of the mine. It is recommended to use at least 3 turtles (one for the main trunk and one for a branch on each side of the trunk), but fewer can be used with some manual repositioning. How it works:
* The turtle will mine out a 3x3 area. As it does so, it will compare the blocks in the walls with whatever is placed in its first slot. If that block does not match slot 1, it will be replaced with whatever is in slot 2. For example, I use this with stone in slot 1 and cobblestone in slot 2. This means that anything in the walls that ISN'T stone will be replaced with cobblestone. If you were to place cobblestone in slots 1 and 2, the walls would end up being solid cobblestone. As it mines out these slices, a turtle will place torches so that the tunnel remains safe from mob spawns. For optimum torch utilization, users are recommended to make the length of their tunnels a multiple of 10.
* Before beginning each 3x3 slice of a tunnel, the turtle will check to make sure it has enough materials to adequately complete that slice. If it does not, it will return to the beginning of the branch mine to resupply. If the turtle's inventory gets full, it will also return to this position to unload.
* When the turtles are finished with mining out the branches, they will return to the main trunk and position themselves for the next branch. The user will need to specify the direction that the turtle will need to go (either right or left) to reach the next tunnel position.
* Lastly, more than 1 turtle can be assigned to work on each side of the main trunk (each working on their own tunnels). The number of turtles needs to be specified by the user.
* For specifics of the setup, go to https://imgur.com/a/GJglvsW
*Calling sequence: Safebranch <type> <length> <direction> <# of turtles> <min light lvl>
* <type> can be "side" or "main"
* <length> is the length of the tunnel you want mined
* <direction> is the direction the turtle should go when finished (l or r). This argument may be omitted for "main" tunnels
* Note that this direction is from the turtle's perspective. A turtle on the left side of the branch mine should probably move
to the right when they finish their branch
* <# of turtles> is the number of turtles on this side of the main tunnel. This argument may be omitted for "main" tunnels
* Should be at least 1, but can be as many as you like
* <min light lvl> is the minimum light level that you want to allow in your mine. To block mob spawns:
* For MC versions lower than 1.18, this should be greater than or equal to 8
* For 1.18+, it should be greater than or equal to 1.
Inventory Layout:
1 - Stone
2 - Cobble
3 - Torches
16 - Fuel (Optional)
[Note 1] More recent versions of CC (for minecraft 1.13+) include the ability to waterlog turtles. While this may not cause an issue for small pockets of water, it WILL cause issues for larger pockets or aquifers. There is no way to combat this unless the devs add an option to disable waterlogging. For this reason, I recommend digging a small 1x1x1 hole in the floor at the start of each tunnel to stop any floods that do occur. I know it is annoying to have water sources in the tunnel (it drives me crazy), but in these versions of CC the turtles are incapable of directly removing water. All workarounds that I have considered involve silly things, like giving the turtles sponges and/or buckets, thus taking up valuable inventory space and reducing their effectiveness as mining turtles. For the time being, I suggest using some water proof light source in slot 3 (like lanterns or glowstone). These sorts of workarounds should NOT be necessary on 1.12 and earlier.
--]]
function usage() --Displays usage tips when invalid inputs are entered
usagetext = {
'Usage: Safebranch <type> <length>',
' <direction> <# of turtles>',
' <min light lvl>',
' ',
' ',
'<type> can be "side" or "main"',
' ',
'<length> is the length of the tunnel',
' you want mined',
' ',
'<direction> is the direction the turtle',
' should go when finished (l',
' or r). This argument may be',
' omitted for "main" tunnels',
' ',
'<# of turtles> is the number of turtles',
' on this side of the main',
' tunnel. This argument',
' may be omitted for',
' "main" tunnels',
' ',
'<min light lvl> is the minimum light',
' level that can block',
' mob spawns. This',
' argument may be',
' omitted for "main"',
' tunnels. For MC',
' versions lower than',
' 1.18, this shouldbe 8,',
' for 1.18+,it is 1.',
' ',
'The arguments may be omitted for a text','prompt. For more help, type "Safebranch','help"',''}
textutils.pagedTabulate(usagetext)
return
end
function clc() --Quick command to clear the terminal (I use matlab a lot, so clc is natural for me)
term.clear()
term.setCursorPos(1,1)
end
function stuck() --Displays "I'm stuck" messages
print('I think I might have gotten myself stuck...')
print('Terminate program or press enter after obstacle is cleared.')
read()
end
function searchinv() --Searches turtle's inventory for items like currently selected item, and reloads slot if they are found
local ini_slot = turtle.getSelectedSlot()
if turtle.getFuelLevel() == 'unlimited' then
endslot = 16
else
endslot = 15
end
for i = 4,endslot do
restocktorches() --If turtle is at the reloading station, this makes sure the turtle has at least 32 torches
turtle.select(i)
if turtle.compareTo(ini_slot) then
turtle.transferTo(ini_slot)
if ini_slot == cobble then
if turtle.getItemCount(ini_slot) > 22 then --At most, a turtle will need 22 pieces of cobble for a slice of branch mine. This makes sure he has it
turtle.select(ini_slot)
return true
end
else
turtle.select(ini_slot)
return true
end
end
end
turtle.select(ini_slot)
return false
end
function addfuel() --Checks if a turtle needs fuel, and refuels if it does.
if turtle.getFuelLevel() == 'unlimited' then
elseif turtle.getFuelLevel() == 0 then
local ini_slot = turtle.getSelectedSlot()
turtle.select(fuel)
if turtle.getItemCount() > 1 then
turtle.refuel(1)
elseif turtle.getItemCount() == 1 then
for i = 4,15 do
turtle.select(i)
if turtle.refuel(1) then
break
elseif i == 15 then
turtle.select(fuel)
print('I am out of fuel. Please load fuel into slot '..tostring(fuel))
print('Press enter after fuel is loaded.')
read()
turtle.refuel(1)
end
end
else
print('Slot '..tostring(fuel)..' must contain a fuel item!')
end
turtle.select(ini_slot)
end
end
function tup() --Guarantees that a turtle will move up when told (gravel, sand, water, lava, and mob proof)
addfuel()
local attempt = 0
while turtle.up() == false do
turtle.digUp()
turtle.attackUp()
attempt = attempt + 1
if attempt >= 10 then
stuck()
end
end
end
function tdn() --Guarantees that a turtle will move down when told (gravel, sand, water, lava, and mob proof)
addfuel()
local attempt = 0
while turtle.down() == false do
turtle.digDown()
turtle.attackDown()
attempt = attempt + 1
if attempt >= 10 then
stuck()
end
end
end
function tfd() --Guarantees that a turtle will move forward when told (gravel, sand, water, lava, and mob proof)
addfuel()
local attempt = 0
while turtle.forward() == false do
turtle.dig()
turtle.attack()
attempt = attempt + 1
if attempt >= 10 then
stuck()
end
end
end
function tbk() --Guarantees that a turtle will move back when told (gravel, sand, water, lava, and mob proof)
addfuel()
if turtle.back() == false then
turtle.turnRight()
turtle.turnRight()
tfd()
turtle.turnRight()
turtle.turnRight()
end
end
function cup() --Compares the block above turtle to slot 1 and replaces it with slot 2 if it doesnt match
local ini_slot = turtle.getSelectedSlot()
turtle.select(stone)
if turtle.compareUp() == false then
turtle.select(cobble)
if turtle.compareUp() == false then
if turtle.getItemCount() <= 1 then
if searchinv() == false then
print('I need more of item '..tostring(cobble)..'.')
print('Press enter after reloading...')
read()
end
end
local attempt = 0
while turtle.placeUp() == false do
turtle.digUp()
turtle.attackUp()
attempt = attempt + 1
if attempt >= 10 then
stuck()
end
end
end
end
turtle.select(ini_slot)
end
function cdn() --Compares the block below turtle to slot 1 and replaces it with slot 2 if it doesnt match
local ini_slot = turtle.getSelectedSlot()
turtle.select(stone)
if turtle.compareDown() == false then
turtle.select(cobble)
if turtle.compareDown() == false then
if turtle.getItemCount() <= 1 then
if searchinv() == false then
print('I need more of item '..tostring(cobble)..'.')
print('Press enter after reloading...')
read()
end
end
local attempt = 0
while turtle.placeDown() == false do
turtle.digDown()
turtle.attackDown()
attempt = attempt + 1
if attempt >= 10 then
stuck()
end
end
end
end
turtle.select(ini_slot)
end
function cfd() --Compares the block in front of turtle to slot 1 and replaces it with slot 2 if it doesnt match
local ini_slot = turtle.getSelectedSlot()
turtle.select(stone)
if turtle.compare() == false then
turtle.select(cobble)
if turtle.compare() == false then
if turtle.getItemCount() <= 1 then
if searchinv() == false then
print('I need more of item '..tostring(cobble)..'.')
print('Press enter after reloading...')
read()
end
end
local attempt = 0
while turtle.place() == false do
turtle.dig()
turtle.attack()
attempt = attempt + 1
if attempt >= 10 then
stuck()
end
end
end
end
turtle.select(ini_slot)
end
function placetorch() --Turns turtle around and places a torch
local ini_slot = turtle.getSelectedSlot()
turtle.turnLeft()
turtle.turnLeft()
local attempt = 0
turtle.select(torch)
if turtle.getItemCount() <= 1 then
print('I need more torches in slot '..tostring(turtle.getSelectedSlot())..'.')
print('Press enter after reloading...')
read()
end
tup()
tfd()
while turtle.placeDown() == false do
turtle.attackDown()
turtle.digDown()
attempt = attempt + 1
if attempt >= 10 then
stuck()
end
end
tbk()
tdn()
turtle.turnLeft()
turtle.turnLeft()
turtle.select(ini_slot)
end
function checkstock(position) --Checks to make sure turtle has sufficient supplies for this slice of mining. Position is fed to this function so the turtle can get back to its tunnel if it needs to go restock
position = position or 0
local ini_slot = turtle.getSelectedSlot()
if turtle.getItemCount(stone) < 1 then
turtle.select(stone)
if searchinv() == false then
print('I need more of item '..tostring(stone)..'.')
print('Press enter after reloading...')
read()
end
elseif turtle.getItemCount(cobble) < 22 then
turtle.select(cobble)
if searchinv() == false then
print('Restocking on item '..tostring(cobble)..'.')
restock(position)
end
elseif turtle.getItemCount(torch) < math.ceil(length/5) then
turtle.select(torch)
if searchinv() == false then
print('Restocking on torches.')
restock(position)
end
elseif turtle.getFuelLevel() ~= 'unlimited' and turtle.getItemCount(fuel) < 4 then
turtle.select(fuel)
if searchinv() == false then
print('Restocking on fuel.')
restock(position)
end
else
emptyslots = 0
for i = 1,16 do
if turtle.getItemCount(i) == 0 then
emptyslots = emptyslots + 1
end
end
if emptyslots == 0 then
restock(position)
else
return true
end
end
turtle.select(ini_slot)
end
function restock(position) --Sends the turtle back to the unload/reload chests to restock or deposit excess materials
turtle.turnLeft()
tfd()
turtle.turnLeft()
if tunneltype == 'side' then --Determines if the turtle is a branch miner or trunk miner
for j = 1,position do
tfd()
end
if direction == "r" then --Determines which way the chests are and orients to begin travel
turtle.turnRight()
else
while turtle.forward() == false do
turtle.attack()
end
while turtle.forward() == false do
turtle.attack()
end
turtle.turnLeft()
while turtle.forward() == false do
turtle.attack()
end
while turtle.forward() == false do
turtle.attack()
end
end
end
distfromchest = 0 --This variable keeps up with how far the turtle travels to reach chest so it can get back to its tunnel
while turtle.detect() == false do
while turtle.forward() == false do
addfuel()
turtle.attack()
end
distfromchest = distfromchest + 1
if turtle.detect() then
local boolean, data = turtle.inspect()
if string.find(string.lower(data.name),'turtle') then
print('Detected another turtle. Waiting in line...')
while turtle.detect() do
sleep(7)
end
elseif data.name == 'minecraft:chest' then
else
print('Unknown Obstacle. Wating for clearance.')
print('Press enter to continue...')
read()
end
end
end
local ini_slot = turtle.getSelectedSlot()
if turtle.getItemCount(cobble) < 64 then --Reloads cobble if needed
for i = 4,15 do
restocktorches()
turtle.select(i)
if turtle.compareTo(cobble) then
turtle.transferTo(cobble)
end
end
if turtle.getItemCount(cobble) < 64 then
turtle.select(cobble)
turtle.suckDown()
end
end
if tunneltype == 'side' then
startslot = 4
else
startslot = 5
end
if turtle.getFuelLimit() == 'unlimited' then
endslot = 16
else
endslot = 15
end
for i = startslot,endslot do
restocktorches()
turtle.select(i)
if turtle.compareTo(cobble) then --Deposits excess materials
turtle.dropDown()
else
turtle.drop()
end
end
turtle.select(ini_slot)
tup()
turtle.turnLeft()
tfd()
tfd()
tdn()
turtle.turnLeft()
for z = distfromchest,1,-1 do --Returns to branch or main trunk end
tfd()
end
if tunneltype == 'side' then
if direction == 'l' then
turtle.turnRight()
else
tfd()
tfd()
turtle.turnLeft()
tfd()
tfd()
end
for j = 1, position do
tfd()
end
end
turtle.turnLeft()
tfd()
turtle.turnRight()
end
function restocktorches() --Controls whether the hopper at the restock chests will load more torches into turtle
if turtle.getItemCount(torch) > 31 then
rs.setOutput('right',true)
else
rs.setOutput('right',false)
end
end
function moveover() --Once turtle is done with branch, this function makes it return to the trunk and position itself for the next branch
tup()
turtle.turnRight()
turtle.turnRight()
turtle.select(torch)
remainder = (length/(2*(13-msll)-math.floor(length/(2*(13-msll)))*(2*(13-msll))))
for i = length,1,-1 do
tfd()
if i == length and remainder <(12-msll) then --Removes excess torches that are not needed. Light level will stay above msll
turtle.digDown()
elseif i/(13-msll) == math.floor(i/(13-msll)) and i/(2*(13-msll)) ~= math.floor(i/(2*(13-msll))) then
turtle.digDown()
end
end
if direction == 'l' then
turtle.turnRight()
else
turtle.turnLeft()
end
for i = 1,5*turtles do
turtle.forward()
end
turtle.down()
if direction == 'l' then
turtle.turnRight()
else
turtle.turnLeft()
end
end
function progress(i) --Function to display progress bar while mining
percent = (i+1)/length
clc()
print('Mining in progress...')
print()
print()
print('< >')
term.setCursorPos(2,4)
bar = math.ceil(percent*35)
for j = 1,bar do
write('=')
end
term.setCursorPos(17,5)
print(tostring(percent*100-percent*100%0.1)..'%')
end
---------------------------------------
-----------------CODE------------------
---------------------------------------
local args = {...}
stone = 1 --Slot index for materials
cobble = 2
torch = 3
fuel = 16
helptext = {
'Safebranch is designed to mine out a ','branch mine with 3x3 tunnels with ','multiple turtles mining their own ','branches simultaneously. As they mine, ','they will remove any ores from the ','walls, and fill in empty space to block ','off natural caverns, water, lava, etc. ','In addition, they will place down ','torches periodically to prevent mobs ','from spawning. To work as intended, it ','is recommended to have at least 3 ','turtles going at a time (1 on the main ','"trunk" of the mine, and 1 for each ','branch on either side, but you can use ','as few as 1 turtle with manual ','placement after each tunnel. Below is a','diagram of the intended usage. The Ds ','represent walls, with "dashed" lines ','representing the excavation path of the','turtles.',' ',' D D',' sideshaft',' D D',' ',' D D','DDDDDDDDDDDDDDDDD D D D D D D D',' T D',' TD mainshaft',' T D','DDDDDDDDDDDDDDDDD D D D D D D D',' D D',' ',' D D',' sideshaft',' D D',' '}
if #args == 0 then --If no arguments, give a text prompt instead
print('Is this a side branch or the main shaft? ')
write('Type main or side: ')
tunneltype = string.lower(read())
print()
print('How long do you want the tunnel to be?')
write('Enter a number greater than 0: ')
length = tonumber(read())
if tunneltype == 'side' then
print()
print('Once the turtle is finished, should it move to the left or right to start the next one?')
write('Type either L or R: ')
direction = string.lower(read())
print()
print('How many turtles (including this one) are on this side of the branch mine?')
write('Enter a number greater than 0: ')
turtles = tonumber(read())
end
write('What is the minimum safe light level (8 or 1): ')
msll = tonumber(read())
elseif string.lower(args[1]) == 'help' then
clc()
textutils.pagedTabulate(helptext)
return
elseif #args == 2 then
if string.lower(args[1]) ~= 'main' then
usage()
return
end
tunneltype = string.lower(args[1])
length = tonumber(args[2])
msll = 1
elseif string.lower(args[1]) == 'side' and tonumber(args[2]) > 0 and (string.lower(args[3]) == 'l' or string.lower(args[3]) == 'r') and tonumber(args[4]) >= 1 and tonumber(args[5]) then
tunneltype = string.lower(args[1])
length = tonumber(args[2])
direction = string.lower(args[3])
turtles = tonumber(args[4])
msll = tonumber(args[5])
else
usage()
return
end
clc()
for i = 0,length-1 do
checkstock(i) --Checks to make sure turtle has enough materials
if i ~= 0 then --Checks to see if turtle needs to place a torch behind itself
if tunneltype == 'main' and i/5 == math.floor(i/5) then
placetorch()
elseif tunneltype == 'side' and i/(13-msll) == math.floor(i/(13-msll)) then
placetorch()
end
end
--Middle column of slice
tfd()
cfd()
cdn()
tup()
cfd()
tup()
cfd()
cup()
turtle.turnLeft()
--Left column of slice
tfd()
cfd()
cup()
turtle.turnRight()
cfd()
tdn()
cfd()
turtle.turnLeft()
cfd()
tdn()
cfd()
cdn()
turtle.turnRight()
cfd()
turtle.turnRight()
--Right column of slice
tfd()
tfd()
cfd()
cdn()
turtle.turnLeft()
cfd()
tup()
cfd()
turtle.turnRight()
cfd()
tup()
cfd()
cup()
turtle.turnLeft()
cfd()
turtle.turnLeft()
tfd()
turtle.turnRight()
tdn()
tdn()
progress(i) --Update progress bar
if i == length-1 then --Place torch at end of tunnel
placetorch()
if tunneltype == 'side' then
moveover()
end
end
end
turtle.select(1)