Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --new mining script for turtle drone
- --declare variables for the entire code
- local locationFile --handle for the location file read and writes
- local deltaXNow,deltaYNow,deltaZNow,orientation --variables to hold change in coordinates from "home" location.
- local yHome --the "home" y level one block below the mining boss
- local modem --modem handle
- local listenPort
- local coroutineAction --what action should be taken during the coroutine call
- local turtleID --id of the turtle
- local miningStatus = 0--if the turtle is mining hold a variable for requests this is used in miningCoroutine to resume state
- local itemDetails --table to pass results of turtle.inspect() between coroutines
- local junkItems = {} --table to hold all junk items
- --create the table of junk items to not mine
- local junkFile = io.open("junk","r") --open the file junkFile
- repeat
- junkItems[junkFile.read("*line") or "endOfLine"] = true --save the line from file as the key set value true until all lines are done then set key endOfLine true
- until junkItems["endOfLine"] --file is all imported
- io.close(junkFile) --close the file
- ------
- --coroutines for movement without losing rednet messages.
- local actionCoroutine = coroutine.create(function(coroutineAction)
- while true do
- print("actionCoroutine called with "..coroutineAction)--move the turtle in the requested direction
- --turtle orientation is n=1,e=2,s=3,w=4
- if coroutineAction == "forward" then
- while not turtle.forward() do --if the turtle cannot move forwards
- if turtle.detect() then --if there is a block in front
- if turtle.dig() then --dig it
- digTimerID = os.startTimer(0.35) --start a timer until the dig action completes
- coroutine.yield("digging") --yield the coroutine until the dig timer expires
- else
- --something is very wrong-----------------------------------------------------------------------------------------
- end
- elseif turtle.attack() then --if it hits a mob
- attackTimerID = os.startTimer(0.4) -- to prevent code hangs this loop may only execute once every 0.4 seconds
- coroutine.yield("attacking") --yield the coroutine until the attack timer fires
- end
- end
- updateLocation(1)
- actionTimerID = os.startTimer(0.35) --turtle is now moving forwards successfully, 0.35s until move completion
- elseif coroutineAction == "down" then
- while not turtle.down() do --if the turtle cannot move down
- if turtle.detectDown() then --if there is a block below
- if turtle.digDown() then --then dig it
- digTimerID = os.startTimer(0.35)
- coroutine.yield("digging")
- else
- --assume bedrock
- --transmit to mining boss bedrock
- coroutine.resume(miningCoroutine,true)
- break --exit the while not turtle.down loop
- end
- elseif turtle.attackDown() then --if it hits a mob
- attackTimerID = os.startTimer(0.4) -- to prevent code hangs this loop may only execute once every 0.4 seconds
- coroutine.yield("attacking") --yield the coroutine until the attack timer fires
- end
- end
- deltaYNow = deltaYNow - 1
- writeFileBackup()
- actionTimerID = os.startTimer(0.35) --turtle is now moving down successfully, 0.35s until move completion
- elseif coroutineAction == "up" then
- while not turtle.up() do --if the turtle cannot move down
- if turtle.detectUp() then --if there is a block below
- if turtle.digUp() then --then dig it
- digTimerID = os.startTimer(0.35)
- coroutine.yield("digging")
- else
- --something is very very wrong
- end
- elseif turtle.attackUp() then --if it hits a mob
- attackTimerID = os.startTimer(0.4) -- to prevent code hangs this loop may only execute once every 0.4 seconds
- coroutine.yield("attacking") --yield the coroutine until the attack timer fires
- end
- end
- deltaYNow = deltaYNow + 1 --alter current displacement
- writeFileBackup() --backup the change immediately
- actionTimerID = os.startTimer(0.35) --turtle is now moving up successfully, 0.35s until move completion
- elseif coroutineAction == "left" then
- turtle.turnLeft() --turn left
- orientation = (orientation - 1) % 4 --turtle is now facing to the left of previous
- actionTimerID = os.startTimer(0.35) --turtle is now turning, 0.35s until move completion
- elseif coroutineAction == "right" then
- turtle.turnRight() --turn right
- orientation = (orientation + 1) % 4 --turtle is now facing to the right of previous
- actionTimerID = os.startTimer(0.35) --turtle is now turning, 0.35s until move completion
- elseif coroutineAction == "inspect" then --turtle inspects the block in front
- print("Inspect reached")
- itemDetails = {turtle.inspect()} --see what's in front of the turtle
- actionTimerID = os.startTimer(0.5)
- print("Timer set ID:"..actionTimerID)
- elseif coroutineAction == "dig" then --dig the block in front of the turtle
- turtle.dig()
- actionTimerID = os.startTimer(0.35) --0.35 till block is dug
- elseif coroutineAction == "unloadInventory" then --the inventory is full empty it into an enderchest
- turtle.select(1)
- if not turtle.placeUp() then --for some reason the turtle can't place the chest above it
- if turtle.detectUp() then --if there is a block above
- if turtle.digUp() then --then dig it
- digTimerID = os.startTimer(0.35)
- coroutine.yield("digging")
- else
- --something is very very wrong
- end
- elseif turtle.attackUp() then --if it hits a mob
- attackTimerID = os.startTimer(0.4) -- to prevent code hangs this loop may only execute once every 0.4 seconds
- coroutine.yield("attacking") --yield the coroutine until the attack timer fires
- end
- end
- placeTimerID = os.startTimer(0.35)
- coroutine.yield()
- for i=2,16 do
- turtle.select(i)
- turtle.dropUp()
- placeTimerID = os.startTimer(0.5)
- coroutine.yield()
- end
- turtle.select(1) --move the selected slot back to 1
- turtle.digUp() --collect the ender chest
- actionTimerID = os.startTimer(0.35) --item drop off is finished
- end
- coroutineAction = false
- --coroutine.yield()
- end
- end)
- local stage = false --is set to true when hitting bedrock in actionCoroutine
- local miningCoroutine = coroutine.create(function(stage)
- print("miningCoroutine started")
- local function checkAndMine() --this is only used inside the mining coroutine
- print("check and mine function called")
- coroutine.resume(actionCoroutine,"inspect") --inspect the block in front
- print("inspect passed")
- coroutine.yield()
- if not junkItems[itemDetails[2].name] then --run the actionCoroutine to see what the block in front is
- coroutine.resume(actionCoroutine,"dig") --dig the non junk block
- coroutine.yield()
- end
- end
- print("starting first repeat")
- repeat
- print("just after first repeat miningStatus = "..miningStatus)
- if not (miningStatus > 1) then --if the miner has progressed past stage 1(or needs to skip turning for the first action)
- print("inside first repeat mine block 1")
- checkAndMine()
- coroutine.resume(actionCoroutine,"left")
- coroutine.yield("waiting")
- elseif miningStatus == 2 then --if it was only skip once then downgrade the status to 1
- miningStatus = 1
- writeFileBackup()
- end
- if not (miningStatus > 1) then --if the turtle has progressed past all of this section skip,
- checkAndMine()
- coroutine.resume(actionCoroutine,"down")
- coroutine.yield("waiting")
- if stage then
- miningStatus = 3
- writeFileBackup()
- stage = false
- end
- end
- until miningStatus >= 3 --this stage is done if the status is equal or higher than 3
- if not (miningStatus > 4) then
- coroutine.resume(actionCoroutine,"right")
- miningStatus = 4
- writeFileBackup()
- coroutine.yield("waiting")
- elseif not (miningStatus > 5) then
- coroutine.resume(actionCoroutine,"right")
- miningStatus = 5
- writeFileBackup()
- coroutine.yield("waiting")
- end
- repeat
- if miningStatus == 6 then
- miningStatus = 5
- writeFileBackup()
- else
- checkAndMine()
- coroutine.resume(actionCoroutine,"right")
- coroutine.yield("waiting")
- end
- checkAndMine()
- coroutine.resume(actionCoroutine,"up")
- coroutine.yield("waiting")
- until yHome == deltaYNow
- modem.transmit(2999,listenPort,"miningFinihed")
- miningStatus = 0
- end)
- --code functions
- local function writeFileBackup() --write all the variables to file in case of unexpected shutdown
- locationFile = io.open("location","w") --open a new empty file, overwrite the previous file
- locationFile.write(deltaXNow,"/n",deltaYNow,"/n",deltaZNow,"/n",orientation,"/n",turtleID,"/n",yHome,"/n",miningStatus) --write all the variables
- io.close(LocationFile)
- end
- local direction -- passes parameter from function updateLocation
- local function updateLocation(direction) --pass +1 to move forwards and -1 to go backwards
- --based on orientation adjust the current location when moving "forwards"
- if orientation == 0 then
- deltaXNow = deltaZNow - direction
- elseif orientation == 1 then
- deltaXNow = deltaXNow - direction
- elseif orientation == 2 then
- deltaZNow = deltaZNow + direction
- elseif orientation == 3 then
- deltaXNow = deltaXNow + direction
- end
- writeFileBackup() --backup the change to file
- end
- --------
- --run on startup
- --wrap the modem and begin listening
- local modem = peripheral.wrap("right") --wrap the peripheral on the right, (modem)
- --load the saved delta from the store file locationFile
- locationFile=io.open("location","r")
- if locationFile == nil then --if the file does not exist then exit script, else save the handle
- --for a turtle freshly placed with no assigned ID assume has been placed underneath the mining boss in the same orientation, this is important.
- modem.open(3000) --listen on channel 3000
- modem.transmit(2999,3000,"new_miner")
- local recievedTable = {} -- a table to hold all the received location and orientation data
- for i = 1 , 5 do
- local eventQueue = {os.pullEventRaw("modem_message")} --pull only modem message events from the event Queue
- recievedTable[i] = tonumber(eventQueue[5])
- end
- deltaXNow = recievedTable[1]--pull stored locations from the received rednet
- deltaYNow = recievedTable[2]
- deltaZNow = recievedTable[3]
- orientation = recievedTable[4]
- turtleID = recievedTable[5]
- yHome = deltaYNow
- modem.close(3000) --this port is ONLY for initial config
- else
- deltaXNow = tonumber(locationFile.read("*line")) --pull stored locations from file
- deltaYNow = tonumber(locationFile.read("*line")) --"
- deltaZNow = tonumber(locationFile.read("*line")) --"
- orientation = tonumber(locationFile.read("*line")) --"
- turtleID = tonumber(locationFile.read("*line")) --"
- yHome = tonumber(locationFile.read("*line"))
- miningStatus = tonumber(locationFile.read("*line"))
- io.close(locationFile) --close the file
- print(miningStatus)
- if miningStatus > 0 then --if the turtle shutdown mid mining then
- print("miningstatus is > 0")--calculate exactly what point of the mining action it was doing
- if ((((deltaYNow - 1) % 4) == orientation) and (miningStatus == 1)) then --if the turtle has already turned at this y level
- miningStatus = 2 --skip the turn action and go down
- elseif (not (((deltaYNow - 2) % 4) == orientation) and (miningstatus == 5)) then --if it has already turned comming up
- miningStatus = 6 --skip the turn and move up
- end
- coroutine.resume(miningCoroutine) --trigger the coroutine movement and all associated timers that should set the entire thing going
- end
- end
- listenPort = turtleID --the listen port is the same as the turtle ID
- modem.open(listenPort) --open the listening port
- -- main code body here
- --declare local variables
- local actionTimerID --numerical ID for action cooldown
- local attackTimerID --numerical timer for attack action cooldown
- local digTimerID --numerical timer for attack action cooldown
- local placeTimerID
- while true do
- print(actionTimerID)
- local eventQueue = {os.pullEventRaw()} --pull ALL events from the event Queue
- --sleep(3)
- print(eventQueue[1]," ",eventQueue[2]," ",eventQueue[3]," ",eventQueue[4])
- if eventQueue[1] == "terminate" then -- if it is a user generated terminate event
- modem.transmit(2999,listenPort,"terminate") --inform the boss that this turtle has terminated
- print("Terminate Event") --print to log that this is a user triggered terminate
- exit() --end
- elseif eventQueue[1] == "timer" then --a timer has triggered
- print("timer event switch")
- exit(0)
- if eventQueue[2] == actionTimerID then --the turtle has finished the action and may act again
- print("action timer fired and found")
- if miningStatus > 0 then --if the turtle is still mining down or up then
- print("turtle is mid mining")
- coroutine.resume(miningCoroutine) --continue this action
- else --report in all done
- --transmit to boss
- end
- elseif eventQueue[2] == attackTimerID then --the turtle has finished attacking and may attack again
- coroutine.resume(actionCoroutine) --resume the coroutine on line 30
- elseif eventQueue[2] == digTimerID then --the turtle has finished digging so resume the coroutine
- coroutine.resume(actionCoroutine) --resume the coroutine on line 24
- elseif eventQueue[2] == placeTimerID then --the turtle has finished digging so resume the coroutine
- coroutine.resume(actionCoroutine) --resume the coroutine on line 115
- end
- elseif eventQueue[1] == "turtle_response" then --a java handled action has completed, the coroutine can now function again, pass the result to the coroutine to unlock it and begin a timer for the action to complete if it succeeded
- print("passback to coroutine")
- coroutine.resume(actionCoroutine, unpack(eventQueue)) --results are handled in the coroutine
- elseif eventQueue[1] == "modem_message" then --orders received from the mining boss
- if eventQueue[5] == "mine" then --when the mining boss sends mine down
- miningStatus = 1
- writeFileBackup()
- coroutine.resume(miningCoroutine) --start mining the column
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment