Skip to content

Instantly share code, notes, and snippets.

@CoderPuppy
Created February 6, 2025 05:33
Show Gist options
  • Save CoderPuppy/a1218ce07bf25a7fe15fc274a08c3dea to your computer and use it in GitHub Desktop.
Save CoderPuppy/a1218ce07bf25a7fe15fc274a08c3dea to your computer and use it in GitHub Desktop.
[CC] Shaft Miner
local FUEL_TARGET = 1024
local FILLER_TARGET = 128
local ignore_blocks = {
['minecraft:stone'] = true;
['minecraft:cobblestone'] = true;
-- ['minecraft:andesite'] = true;
-- ['minecraft:diorite'] = true;
-- ['minecraft:granite'] = true;
-- ['minecraft:dirt'] = true;
['minecraft:deepslate'] = true;
['minecraft:cobbled_deepslate'] = true;
['minecraft:tuff'] = true;
['minecraft:ladder'] = true;
}
local whitelist_fuel = {
['minecraft:coal'] = true;
}
local whitelist_filler = {
['minecraft:stone'] = true;
['minecraft:cobblestone'] = true;
-- ['minecraft:andesite'] = true;
-- ['minecraft:diorite'] = true;
-- ['minecraft:granite'] = true;
-- ['minecraft:dirt'] = true;
['minecraft:deepslate'] = true;
['minecraft:cobbled_deepslate'] = true;
['minecraft:tuff'] = true;
}
local whitelist_bucket = {
['minecraft:lava'] = true;
}
local blacklist_dig = {
['minecraft:amethyst_cluster'] = true;
['minecraft:budding_amethyst'] = true;
}
local T = {}
T.up = {
name = 'up';
peripheral_dir = 'top';
delta_y = 1;
attack = turtle.attackUp;
compare = turtle.compareUp;
dig = turtle.digUp;
drop = turtle.dropUp;
inspect = turtle.inspectUp;
move = turtle.up;
place = turtle.placeUp;
suck = turtle.suckUp;
}
T.down = {
name = 'down';
peripheral_dir = 'bottom';
delta_y = -1;
attack = turtle.attackDown;
compare = turtle.compareDown;
dig = turtle.digDown;
drop = turtle.dropDown;
inspect = turtle.inspectDown;
move = turtle.down;
place = turtle.placeDown;
suck = turtle.suckDown;
}
T.forward = {
name = 'forward';
peripheral_dir = 'front';
delta_y = 0;
attack = turtle.attack;
compare = turtle.compare;
dig = turtle.dig;
drop = turtle.drop;
inspect = turtle.inspect;
move = turtle.forward;
place = turtle.place;
suck = turtle.suck;
}
T.back = {
name = 'back';
peripheral_dir = 'back';
delta_y = 0;
move = turtle.back;
}
T.direction = 0
T.pos_y = 0
T.inspect_cache = {}
function T.move(dir)
T.pos_y = T.pos_y + dir.delta_y
T.inspect_cache = {}
print('move', dir.name)
return dir.move()
end
function T.inspect(dir)
local cached = T.inspect_cache[dir]
if cached ~= nil then
return cached
else
local full, details = dir.inspect()
if not full then
details = false
end
T.inspect_cache[dir] = details
return details
end
end
function T.turnTo(dir)
local delta = (dir - T.direction) % 4
if delta == 0 then
elseif delta == 1 then
T.right()
elseif delta == 2 then
T.right()
T.right()
elseif delta == 3 then
T.left()
else
error('T.turnTo: bad delta: ' .. tostring(delta))
end
end
function T.left()
T.direction = (T.direction - 1) % 4
T.inspect_cache = {}
local ok, err = turtle.turnLeft()
if not ok then
error('T.left: turtle.turnLeft failed: ' .. err)
end
end
function T.right()
T.direction = (T.direction + 1) % 4
T.inspect_cache = {}
local ok, err = turtle.turnRight()
if not ok then
error('T.right: turtle.turnRight failed: ' .. err)
end
end
local args = table.pack(...)
local start_y = tonumber(args[1])
T.pos_y = tonumber(args[2])
local slot_dim_chest = 1
local slot_buckets = 2
local slot_filler
local function identify_inv(details)
if not details then
return nil
elseif whitelist_filler[details.name] then
return 'filler'
elseif whitelist_fuel[details.name] and turtle.getFuelLevel() < FUEL_TARGET then
return 'fuel'
elseif details.name == 'minecraft:bucket' then
return 'bucket'
elseif details.name == 'dimstorage:dimensional_chest' then
return 'dimensional_chest'
else
return 'product'
end
end
local function clear_inventory(dir)
local ok, err
turtle.select(slot_dim_chest)
ok, err = dir.place()
if not ok then
error('clear_inventory: place: ' .. err)
end
T.inspect_cache[dir] = nil
local num_filler = 0
for i = 1, 16 do
local details = turtle.getItemDetail(i)
local decision = identify_inv(details)
if decision == nil then
elseif decision == 'filler' then
num_filler = num_filler + details.count
turtle.select(i)
for j = 3, i do
turtle.transferTo(j)
slot_filler = j
end
elseif decision == 'fuel' then
turtle.select(i)
turtle.refuel(details.count)
elseif decision == 'bucket' then
if i ~= slot_buckets then
turtle.select(i)
turtle.transferTo(slot_buckets)
end
elseif decision == 'dimensional_chest' then
if i ~= slot_dim_chest then
turtle.select(i)
turtle.transferTo(slot_dim_chest)
end
elseif decision == 'product' then
turtle.select(i)
ok, err = dir.drop()
if not ok then
print('clear_inventory: drop failed: ' .. err)
end
else
error('clear_inventory: invalid decision: ' .. tostring(decision))
end
end
sleep(1)
local dc = peripheral.wrap(dir.peripheral_dir)
for i = dc.size(), 1, -1 do
if not dc.getItemDetail(1) then
break
end
dc.pushItems(dir.peripheral_dir, 1, nil, i)
end
local need_buckets = 16 - turtle.getItemCount(slot_buckets)
for i, item in pairs(dc.list()) do
if item.name == 'minecraft:bucket' and need_buckets > 0 then
local num = math.min(item.count, need_buckets)
dc.pushItems(dir.peripheral_dir, i, num, 1)
turtle.select(slot_buckets)
assert(dir.suck(num))
need_buckets = need_buckets - num
elseif num_filler < FILLER_TARGET and whitelist_filler[item.name] then
local num = math.min(item.count, FILLER_TARGET - num_filler)
dc.pushItems(dir.peripheral_dir, i, num, 1)
turtle.select(3)
assert(dir.suck(num))
num_filler = num_filler + num
elseif whitelist_fuel[item.name] and turtle.getFuelLevel() < FUEL_TARGET then
dc.pushItems(dir.peripheral_dir, i, nil, 1)
turtle.select(16)
assert(dir.suck())
assert(turtle.refuel(item.count))
end
end
-- TODO: refill buckets
turtle.select(1)
ok, err = dir.dig()
if not ok then
error('clear_inventory: dig failed: ' .. err)
end
end
local function dig(dir)
-- loop for additional digs when we need to clear inventory
while true do
local inspect = T.inspect(dir)
if inspect and whitelist_bucket[inspect.name] then
turtle.select(slot_buckets)
local ok, err = dir.place()
if not ok then
return ok, err
end
T.inspect_cache[dir] = nil
local buckets = turtle.getItemDetail(slot_buckets)
if turtle.getItemCount(15) > 0 or not buckets or buckets.name ~= 'minecraft:bucket' then
if T.inspect(dir) then
-- continue loop
else
clear_inventory(dir)
return true
end
else
return true
end
elseif inspect and blacklist_dig[inspect.name] then
return false, 'blacklisted: ' .. inspect.name
else
turtle.select(1)
local ok, err = dir.dig()
if not ok then
return ok, err
end
T.inspect_cache[dir] = nil
if turtle.getItemCount(15) > 0 then
if T.inspect(dir) then
-- continue loop
else
clear_inventory(dir)
return true
end
else
return true
end
end
end
end
local function scan_inventory()
for slot = 1, 16 do
local details = turtle.getItemDetail(slot)
local decision = identify_inv(details)
if decision == 'fuel' then
turtle.select(slot)
turtle.refuel()
elseif decision == 'filler' then
slot_filler = slot
end
end
end
local function place_filler(dir)
if not slot_filler then
scan_inventory()
end
if not slot_filler then
dig(dir)
clear_inventory(dir)
end
if not slot_filler then
scan_inventory()
end
turtle.select(slot_filler)
local ok, err = dir.place()
if not ok then
print('place_filler: place failed: ' .. err)
end
if turtle.getItemCount(slot_filler) == 0 then
slot_filler = nil
end
T.inspect_cache[dir] = nil
end
local function check_side()
while true do
local inspect = T.inspect(T.forward)
print('check_side', inspect and inspect.name)
if inspect and ignore_blocks[inspect.name] then
return
elseif not inspect then
break
else
local ok, err = dig(T.forward)
if not ok then
print('check_side: dig failed: ' .. err)
break
end
end
end
place_filler(T.forward)
end
local function check_sides()
check_side()
T.right()
check_side()
T.right()
check_side()
T.right()
check_side()
end
local function mine_down()
while true do
check_sides()
if not dig(T.down) then
print('dig down failed')
end
if not T.move(T.down) then
break
end
if T.pos_y > -59 then
place_filler(T.up)
end
end
end
local function up_from_bedrock()
while T.pos_y < -58 do
if not T.move(T.up) then
break
end
place_filler(T.down)
end
end
local function mine_up()
while T.pos_y < start_y do
check_sides()
while dig(T.up) do
end
if not T.move(T.up) then
break
end
place_filler(T.down)
end
end
local function move_over(dir)
local ok, err
T.turnTo(dir)
while true do
ok, err = T.move(T.forward)
if ok then
break
end
print('move_over: move 1 failed: ' .. err)
ok, err = dig(T.forward)
if not ok then
print('move_over: dig 1 failed: ' .. err)
end
end
ok, err = dig(T.forward)
if not ok then
print('move_over: dig 2 failed: ' .. err)
end
T.right()
T.right()
place_filler(T.forward)
ok, err = T.move(T.back)
if not ok then
print('move_over: move 2 failed: ' .. err)
T.right()
T.right()
while true do
ok, err = T.move(T.forward)
if ok then
break
end
print('move_over: move 2f failed: ' .. err)
ok, err = dig(T.forward)
if not ok then
print('move_over: dig 2f failed: ' .. err)
end
end
T.right()
T.right()
end
place_filler(T.forward)
T.left()
while true do
ok, err = T.move(T.forward)
if ok then
break
end
print('move_over: move 3 failed: ' .. err)
ok, err = dig(T.forward)
if not ok then
print('move_over: dig 3 failed: ' .. err)
end
end
end
scan_inventory()
-- turtle.select(1)
-- T.up.dig()
-- clear_inventory(T.up)
-- check_sides()
-- while true do
-- mine_down()
-- up_from_bedrock()
--
-- move_over(0)
--
-- mine_down()
-- up_from_bedrock()
--
-- mine_up()
--
-- check_sides()
-- move_over(0)
-- end
for i = 1, 5 do
mine_down()
up_from_bedrock()
move_over(0)
mine_down()
up_from_bedrock()
mine_up()
check_sides()
move_over(0)
end
move_over(1)
for i = 1, 5 do
mine_down()
up_from_bedrock()
move_over(2)
mine_down()
up_from_bedrock()
mine_up()
check_sides()
move_over(2)
end
move_over(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment