Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- quarry.lua
- -- Load the serialization library from https://pastebin.com/aYBdRqXm
- -- Function to fetch and load the serialization library if it doesn't exist
- local function fetchSerializationLibrary()
- if not fs.exists("serialization") then
- print("Fetching serialization library from Pastebin...")
- shell.run("pastebin get aYBdRqXm serialization")
- end
- end
- -- Fetch the serialization library if needed
- fetchSerializationLibrary()
- -- Load the serialization library
- local serialization = require("serialization")
- -- Log file configuration
- local LOG_FILE = "turtle_log.txt"
- -- Function to write messages to the log file
- local function logMessage(message)
- local file = fs.open(LOG_FILE, "a")
- file.writeLine(os.date("[%Y-%m-%d %H:%M:%S] ") .. message)
- file.close()
- end
- -- Get command-line arguments
- local args = { ... }
- -- Function to prompt the user for a number input, with validation
- local function promptUser(prompt, default, min, max)
- while true do
- print(prompt)
- local input = read()
- if input == "" and default ~= nil then
- return default
- end
- local num = tonumber(input)
- if num and (not min or num >= min) and (not max or num <= max) then
- return num
- else
- print("Invalid input. Please enter a number between " .. (min or "-∞") .. " and " .. (max or "∞") .. ".")
- end
- end
- end
- -- Function to prompt the user for a yes/no input
- local function promptYesNo(prompt)
- while true do
- print(prompt .. " (yes/no): ")
- local input = read():lower()
- if input == "yes" or input == "y" then
- return true
- elseif input == "no" or input == "n" then
- return false
- else
- print("Invalid input. Please enter 'yes' or 'no'.")
- end
- end
- end
- -- Configuration
- local STATE_FILE = "resume.us"
- local STARTUP_FILE = "startup.lua"
- local STATE_BACKUP = "stateFile" -- Optional state backup
- -- List of blocks to ignore while mining
- local ignoredBlocks = {
- ["minecraft:stone"] = true,
- ["minecraft:granite"] = true,
- ["minecraft:diorite"] = true,
- ["minecraft:andesite"] = true,
- ["minecraft:gravel"] = true,
- ["minecraft:sand"] = true,
- ["minecraft:dirt"] = true,
- ["minecraft:bedrock"] = true,
- ["minecraft:cobblestone"] = true,
- ["minecraft:chest"] = true -- Ignoring chests
- }
- -- Function to create the startup script
- local function createStartupScript()
- if not fs.exists(STARTUP_FILE) then
- local startup = [[
- -- Startup Script for Quarry Turtle
- -- Automatically runs quarry.lua with resume.us
- shell.run("quarry.lua", "resume")
- ]]
- local file = fs.open(STARTUP_FILE, "w")
- file.write(startup)
- file.close()
- end
- end
- -- Function to save the turtle's current position and state
- local function saveState(state)
- local success, err = serialization.saveTableToFile(state, STATE_FILE)
- if success then
- logMessage("State saved successfully.")
- else
- logMessage("Error saving state: " .. err)
- end
- end
- -- Function to load the turtle's current position and state
- local function loadState()
- local state, err = serialization.loadTableFromFile(STATE_FILE)
- if state then
- -- Check and set default values if missing
- state.width = state.width or 5
- state.length = state.length or 5
- state.height = state.height or 30
- state.currentX = state.currentX or 1
- state.currentY = state.currentY or 1
- state.currentZ = state.currentZ or 1
- state.direction = state.direction or 0 -- 0: Initial Direction
- return state
- else
- logMessage("Error loading state: " .. err)
- return nil
- end
- end
- -- Function to initialize the cuboid grid and starting position
- local function initializeState()
- print("=== Quarry Configuration ===")
- local width = promptUser("Enter the width of the cuboid grid (X dimension): ", 5, 1, 10)
- local length = promptUser("Enter the length of the cuboid grid (Y dimension): ", 5, 1, 10)
- local height = promptUser("Enter the height of the shafts (Z dimension): ", 30, 1, 256)
- local spacing = promptUser("Enter the spacing between shafts (default 3): ", 3, 0, 10)
- local coverShafts = promptYesNo("Should the top of the shaft be covered when it leaves the shaft?")
- local state = {
- width = width,
- length = length,
- height = height,
- spacing = spacing,
- coverShafts = coverShafts,
- currentX = 1,
- currentY = 1,
- currentZ = 1,
- direction = 0, -- 0: Initial Direction
- mining = true
- }
- saveState(state)
- createStartupScript()
- logMessage("Initialization complete. Turtle starting at position (1,1).")
- return state
- end
- -- Function to ensure the turtle moves forward, dealing with obstacles
- local function moveForward(steps)
- for i = 1, steps do
- while not turtle.forward() do
- turtle.dig()
- sleep(0.5) -- Wait a bit before trying again
- end
- end
- end
- -- Function to turn the turtle to a specific direction
- local function turnToDirection(state, desiredTurn)
- if desiredTurn == "left" then
- turtle.turnLeft()
- if state and state.direction ~= nil then
- state.direction = (state.direction - 1) % 4
- end
- elseif desiredTurn == "right" then
- turtle.turnRight()
- if state and state.direction ~= nil then
- state.direction = (state.direction + 1) % 4
- end
- elseif desiredTurn == "around" then
- turtle.turnLeft()
- turtle.turnLeft()
- if state and state.direction ~= nil then
- state.direction = (state.direction + 2) % 4
- end
- end
- end
- -- Function to detect if the program is run by startup.lua
- local function isStartup()
- for _, v in ipairs(args) do
- if v == "resume" then
- return true
- end
- end
- return false
- end
- -- Function to delete state files if run by the player
- local function deleteStateFilesOnPlayerRun()
- if not isStartup() then
- if fs.exists(STATE_FILE) then
- fs.delete(STATE_FILE)
- logMessage(STATE_FILE .. " deleted on player run.")
- end
- if fs.exists(STATE_BACKUP) then
- fs.delete(STATE_BACKUP)
- logMessage(STATE_BACKUP .. " deleted on player run.")
- end
- end
- end
- -- Function to mine adjacent blocks if they are not in the ignore list
- local function mineAdjacent()
- -- Check forward
- local success, data = turtle.inspect()
- if success and not ignoredBlocks[data.name] then
- turtle.dig()
- end
- -- Check up
- success, data = turtle.inspectUp()
- if success and not ignoredBlocks[data.name] then
- turtle.digUp()
- end
- -- Check down
- success, data = turtle.inspectDown()
- if success and not ignoredBlocks[data.name] then
- turtle.digDown()
- end
- -- Check left
- turtle.turnLeft()
- success, data = turtle.inspect()
- if success and not ignoredBlocks[data.name] then
- turtle.dig()
- end
- turtle.turnRight() -- Return to original orientation
- -- Check right
- turtle.turnRight()
- success, data = turtle.inspect()
- if success and not ignoredBlocks[data.name] then
- turtle.dig()
- end
- turtle.turnLeft() -- Return to original orientation
- -- Check back
- turtle.turnLeft()
- turtle.turnLeft()
- success, data = turtle.inspect()
- if success and not ignoredBlocks[data.name] then
- turtle.dig()
- end
- turtle.turnLeft()
- turtle.turnLeft() -- Return to original orientation
- end
- -- Function to mine a shaft at the current grid position
- local function mineShaft(state)
- local depth = 0
- while depth < state.height do
- -- Check for bedrock
- if turtle.detectDown() then
- local success, data = turtle.inspectDown()
- if success and data.name == "minecraft:bedrock" then
- logMessage("Bedrock reached at depth " .. depth)
- break
- end
- end
- -- Mine adjacent blocks
- mineAdjacent()
- -- Dig down
- if not turtle.down() then
- turtle.digDown()
- if not turtle.down() then
- logMessage("Cannot move down further at depth " .. depth)
- break
- end
- end
- depth = depth + 1
- saveState(state) -- Save state after each movement
- end
- -- Return to surface
- while depth > 0 do
- if not turtle.up() then
- turtle.digUp()
- if not turtle.up() then
- logMessage("Cannot move up")
- break
- end
- end
- depth = depth - 1
- end
- -- Optionally cover the top of the shaft
- if state.coverShafts then
- turtle.select(1) -- Assuming slot 1 has the covering block
- turtle.placeDown()
- end
- end
- -- Function to delete the state and resume files upon completion
- local function deleteStateFiles()
- if fs.exists(STATE_FILE) then
- fs.delete(STATE_FILE)
- logMessage(STATE_FILE .. " deleted.")
- end
- if fs.exists(STATE_BACKUP) then
- fs.delete(STATE_BACKUP)
- logMessage(STATE_BACKUP .. " deleted.")
- end
- end
- -- Function to check if the inventory is full
- local function isInventoryFull()
- for i = 1, 16 do
- if turtle.getItemCount(i) == 0 then
- return false
- end
- end
- return true
- end
- -- Function to unload items into a chest behind the starting position
- local function unloadItems(state)
- logMessage("Unloading items...")
- -- Move back to starting position
- local stepsX = state.currentX - 1
- local stepsY = state.currentY - 1
- -- Turn around to face back
- turnToDirection(state, "around")
- moveForward(stepsX * (state.spacing + 1))
- -- Turn left to face starting Y direction
- turnToDirection(state, "left")
- moveForward(stepsY * (state.spacing + 1))
- -- Face the chest (assuming it's behind the starting position)
- turnToDirection(state, "around")
- for i = 1, 16 do
- turtle.select(i)
- turtle.drop()
- end
- turtle.select(1)
- -- Return to current position
- -- Move back along Y-axis
- turnToDirection(state, "around")
- moveForward(stepsY * (state.spacing + 1))
- -- Turn right to face original direction
- turnToDirection(state, "right")
- moveForward(stepsX * (state.spacing + 1))
- -- Turn around to face the original mining direction
- turnToDirection(state, "around")
- logMessage("Finished unloading items.")
- end
- -- Main mining loop that resumes or starts the quarrying operation
- local function main()
- -- Delete state files if run by the player
- deleteStateFilesOnPlayerRun()
- -- Load existing state or initialize
- local state = loadState()
- if not state then
- state = initializeState()
- -- Assume the initial direction is the way the turtle is facing
- state.direction = 0
- saveState(state)
- else
- logMessage("Resuming quarry operation.")
- end
- -- Perform the mining operation
- for y = state.currentY, state.length do
- local startX, endX, stepX
- if (y % 2 == 1) then
- -- Moving forward
- startX = state.currentX
- endX = state.width
- stepX = 1
- else
- -- Moving backward
- startX = state.currentX
- endX = 1
- stepX = -1
- end
- for x = startX, endX, stepX do
- -- Mine shaft at current position
- logMessage("Mining at X: " .. x .. " Y: " .. y)
- mineShaft(state)
- saveState(state)
- -- Check if inventory is full
- if isInventoryFull() then
- unloadItems(state)
- end
- -- Move to next shaft position
- if x ~= endX then
- moveForward(state.spacing + 1)
- end
- -- Update current X position
- state.currentX = x + stepX
- end
- -- At the end of the row, move to the next row if needed
- if y < state.length then
- -- Turn to next row
- if (y % 2 == 1) then
- turnToDirection(state, "right")
- moveForward(state.spacing + 1)
- turnToDirection(state, "right")
- else
- turnToDirection(state, "left")
- moveForward(state.spacing + 1)
- turnToDirection(state, "left")
- end
- state.currentY = y + 1
- -- Update current X position for the new row
- state.currentX = endX
- saveState(state)
- end
- end
- logMessage("Mining operation completed.")
- state.mining = false
- saveState(state)
- -- Clean up files when the operation is done
- deleteStateFiles()
- end
- -- Execute the main function
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement