Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[-------------------------------------------------------------------------
- LONESOME BUILDERCRAFT API (LBA) for Computer Craft Turtles
- @Author Bart'Ouille
- @licence GNU-GPL 3.0
- I'll appreciate if you keep credit me if you use or fork this api
- @Version 1.0b
- @Description This API is a complete way to program turtles for building many shapes, including custom ones while automatically managing fuel and materials.
- It handles full control over turtle parameters, provides a complete error handler, a remote command mode and many other features
- Turtles are provided by Computercraft mod for minecraft (http://computercraft.info).
- @Website http://www.liqueurdetoile.com/gaming/lba
- @Channel https://www.youtube.com/channel/UCUavPLdEJR3CL5mIUrSmpXw
- ---------------------------------------------------------------------------]]
- -- Construction functions
- -- function dot(x, y, z, m)
- -- function line(x1, y1, z1, x2, y2, z2, m)
- -- function rectangleY (x1, z1, x2, z2, y, m, filled, thickness)
- -- function xmobFloor(x1, z1, x2, z2, y, m)
- -----------------------------------------------------------------------------
- -- YOUR CODE HERE
- -- Faster than scrolling to the end :)
- -----------------------------------------------------------------------------
- function lba_yourBuild()
- -- Xmob Tower Script with 5 spawning floors
- local xStart = 2
- local yStart = -4
- local zStart = 0
- -- Pilar for climbing
- dot(xStart,yStart,zStart-1, "stone@0")
- -- Initial area for building
- rectangleY (xStart,zStart,xStart+26,zStart+26,yStart,"stone@0", true)
- -- Crashing floor
- rectangleY (xStart,zStart,xStart+26,zStart+26,yStart+1,"stone_slab@0", true)
- -- Pilar for climbing
- for i=1,26 do dot(xStart,yStart+i,zStart-1, "stone@0") end
- -- Pilar + walls for masking light on spawn floors
- for i=27,41 do
- dot(xStart,yStart+i,zStart-1, "stone@0")
- rectangleY(xStart+2,zStart+2,xStart+24,zStart+24,yStart+i,"stone@0",false,1)
- end
- -- Spawning plaforms, surrounded by walls and a 2 blocks path for player moving
- for i=0,4 do
- dot(xStart,yStart+42+3*i,zStart-1, "stone@0")
- rectangleY(xStart,zStart,xStart+26,zStart+26,yStart+42+3*i,"stone_slab@0", false, 2)
- rectangleY(xStart+2,zStart+2,xStart+24,zStart+24,yStart+42+3*i,"stone@0", false, 1)
- xmobFloor(xStart+3,zStart+3,xStart+23,zStart+23,yStart+42+3*i,"stone@0", false, 1)
- dot(xStart,yStart+43+3*i,zStart-1, "stone@0")
- rectangleY(xStart+2,zStart+2,xStart+24,zStart+24,yStart+43+3*i,"stone@0", false, 1)
- dot(xStart,yStart+44+3*i,zStart-1, "stone@0")
- rectangleY(xStart+2,zStart+2,xStart+24,zStart+24,yStart+44+3*i,"stone@0", false, 1)
- end
- -- No roof for prevent spawning while finishing tower equipment
- end
- -----------------------------------------------------------------------------
- -- BASIC OPTIONS
- -----------------------------------------------------------------------------
- -- All positions are stored using the vector feature
- -- CARE : As in game, y axis is the height
- -- You can acces x, y and z coordinates by calling vectorName.x, vectorName.y, vectorName.z
- -- Method to compute position in space
- -- Set this to true for GPS location value
- -- Set this to false for self relative values
- initPositionByGPS = false
- startPosition = 0
- -- Set the turtle for autodigging or autoattack when moving
- autoDig = true -- Care with this one if you don't build from bottom to top layers
- autoAttack = true
- maxTries = 3 -- Number of attempts to dig/attack to be made if stuck while moving
- -----------------------------------------------------------------------------
- -- AUTOREFUEL FEATURES
- -- Autorefuel lets the turtle going for refuel by itsel as needed
- -- In order to work, one slot must be kept free
- -----------------------------------------------------------------------------
- -- Set autoRefuel to false for disabling this feature
- autoRefuelEnabled = true
- -- Turtle position to go when refueling
- -- DO NOT PUT FUEL POSITION BUT TURTLE POSITION (just above for instance)
- fuelPosition = vector.new(0,0,0)
- -- Indicates in which inner slot the turtle must seek fuel (1-16)
- fuelSlot = 1
- -- Indicates which direction the turtle must facing to access fuel chest (suck) and, optionally, garbage chest (for dropping buckets)
- -- With GPS location, direction are 0 for East, 90 for North, 180 for West and 270 for South
- -- With relative coordinates, the direction 0 is the one that the turtle is facing when places in the world. Next values can be found by adding 90 while rotating left hand. If the turtle is facing East when placed, values will be the same than GPS location
- -- Up direction's value is 1 and Down direction's value is -1
- -- If not set, it will throw an error when using autoRefuel feature
- autoRefuelSuckDirection = -1
- autoRefuelDropDirection = 180
- -----------------------------------------------------------------------------
- -- AUTOREFILL MATERIALS FEATURES
- -- Autorefill lets the turtle fetching materials by itself as needed
- -- CAUTION : If used with autorefuel feature, the fuel slot will be locked
- -----------------------------------------------------------------------------
- -- Set autoRefill to false for disabling this feature
- autoRefillEnabled = true
- -- You can provide materials location in two ways
- materialLocation = {}
- registeredMaterials = 0
- -- HINT : LOCKING MATERIALS FOR SLOTS
- -- If you want to make your turtle to always keep the same mix of materials in its inventory, simply fill these slots with at least one block when starting script. The turtle will scan its inventory at startup and keep this mix all the way
- -- If you choose to leave the turtle inventory clear at startup, it will fill it with choosen block at each construction step then unloading and go for next block in case of changing
- -- CARE : If slots are not locked, you can't use a single container for multiple blocks because turtle will only suck the first available stack
- -- Set it to false if you plan to use hard coding way (at yout own risk)
- autoDetectMaterials = true
- -- HINT : For avoidind turtle destroying your containers, set a startRange and a endRange with turtle's basic movement rule (if going down, movement is on x axis, then z axis and finally y axis - If going up, movement is on y axis, then x axis anf finally z axis)
- -- HINT : When refilling materials, turtle will always go first to startRange position, then to chest and leave by going to endRange position
- -- HINT : Better to be a line and you can put many chests to each position
- autoDetectStartPosition = vector.new(0,0,-2) -- Set turtle position start for scanning container's area
- autoDetectEndPosition = vector.new(0,0,-2) -- Set turtle position end for scanning container's area
- -----------------------------------------------------------------------------
- -- REDNET FEATURES
- -- Commit turtle messages through rednet
- -----------------------------------------------------------------------------
- -- COMING SOON !
- -----------------------------------------------------------------------------
- -- GLOBAL VARIABLES FOR STATES AND STATISTICS
- -----------------------------------------------------------------------------
- -- States
- turtleStates = {
- isOnInit = false, -- State when initializing
- isScanningMaterialArea = false, -- State when scanning material area
- isGoingForFuel = false, -- State when fetching fuel
- isGoingForMaterials = false, -- State when fetching materials
- isBuilding = false, -- State when building
- isFuelShortage = true, -- State when running out of fuel
- isMaterialShortage = true, -- State when running out of materials
- isOnError = false, -- State when on error
- isStuck = false -- State when stuck in a place
- }
- -- Log level for verbose (cumulative)
- -- 0 : nothing, 1 : errors, 2 : warnings, 3 : informations, 4 : all sides messages
- logTermLevel = 3 -- Log level for turtle terminal messages
- logRednetLevel = 0 -- Log level for rednet broadcast message
- -- Statistics
- startTime = os.time()
- totalBlocks = 0
- -----------------------------------------------------------------------------
- -- INITIALIZATION AND I/O FUNCTIONS
- -----------------------------------------------------------------------------
- -- @function lba_initialize Mandatory. Launch all subroutines
- -- @function lba_commandMode Enter remote command mode
- -- @function lba_getPosition returns and optionnally display turtle position
- -- @function lba_log generic wrapper for local and rednet display
- -- Performs all initializations requests and settings
- -- MUST BE LAUNCH EACH TIME
- local function lba_initialize()
- turtleStates.isOnInit = true
- lba_log("Lonesome buildercraft init",3)
- -- Coordinates system
- lba_log("Setting coordinates system",3)
- if initPositionByGPS then
- lba_log("Looking for GPS signal...",4)
- local x, y, z = gps.locate()
- if x then
- lba_log("GPS found. Starting calibration",4)
- turtlePosition = vector.new(x,y,z)
- startPosition = turtlePosition
- forward()
- local x, y, z = gps.locate()
- if (turtlePosition.x - x) == 0 then
- if (turtlePosition.z - z) == 1 then
- turtleDirection = 90 -- z decreasing - Facing North
- else
- turtleDirection = 270 -- z increasing - Facing South
- end
- else
- if (turtlePosition.x - x) == 1 then
- turtleDirection = 180 -- x decreasing - Facing West
- else
- turtleDirection = 0 -- x increasing - Facing East
- end
- end
- backward()
- faceTo(0)
- lba_log("Calibration finished",4)
- else
- turtlePosition = vector.new(0,0,0)
- startPosition = turtlePosition
- turtleDirection = 0
- lba_log("No GPS system found. Falling back to relative coordinates system",2)
- lba_log("The turtle is at x=0, z=0, y=0 and facing direction 0",4)
- lba_log("It should be EAST ingame for matching x and z game axis",4)
- lba_log("X are increasing in front of turtle and Z are increasing on right of the turtle",4)
- end
- else
- turtlePosition = vector.new(0,0,0)
- startPosition = turtlePosition
- turtleDirection = 0
- lba_log("Relative coordinates are used",3)
- lba_log("The turtle is at x=0, z=0, y=0 and facing direction 0",4)
- lba_log("It should be matching EAST ingame for matching x and z game axis",4)
- lba_log("X are increasing in front of turtle and Z are increasing on right of the turtle",4)
- end
- -- Tests if turtle is equipped with a pickaxe for autodig and autoattack features
- -- COMING SOON
- -- Fuel System Initialization
- lba_log("Fuel System initialization",3)
- if autoRefuelEnabled then
- lba_log("Refuel : Auto",3)
- lba_log("Checking distance to Fuel supply",4)
- if not(checkIfRefuelNeeded()) then
- lba_log("Enough fuel to start work",3)
- else
- waitForRefuel()
- end
- else
- lba_log("Refuel : Manual. Don't forget me !",3)
- end
- -- Materials initialization
- lba_log("Materials management initialization",3)
- -- Checks inventory for locked slots
- local lockedSlots = false
- for i=1,16 do
- if (i ~= fuelSlot) then
- local m = lba_getSlotContent(i)
- if m then
- if not(materialLocation[m]) then materialLocation[m] = {} end
- if not(materialLocation[m].locked) then materialLocation[m].locked = {i}
- else table.insert(materialLocation[m].locked, i)
- end
- lockedSlots = true
- end
- end
- end
- if lockedSlots then
- lba_log("Locked slots Enabled",3)
- else
- lba_log("Locked slots disabled",3)
- end
- if autoDetectMaterials then
- scanMaterialsArea()
- lba_log("Materials area scan complete",3)
- lba_log(registeredMaterials.." different materials registered",3)
- else
- lba_log("Automatic materials area detection disabled")
- end
- lba_log("Initialization complete\n",3)
- turtleStates.isOnInit = false
- end
- function lba_end()
- goTo(0,0,0)
- faceTo(0)
- local endTime = os.time()
- local elapsed = math.floor((endTime - startTime) * 50)
- local hours = math.floor(elapsed/3600)
- local minutes = math.floor((elapsed/60)%60)
- local seconds = math.floor(elapsed%60%3600)
- lba_log("Job's done!",3)
- lba_log("Elapsed time : "..hours.."h"..minutes.."m"..seconds.."s",3)
- lba_log("Blocks used : "..totalBlocks,3)
- end
- function lba_commandMode()
- -- TODO COMING SOON
- end
- function lba_getPosition(verbose)
- -- @params verbose (optional) If true, will display the position
- verbose = verbose or true
- if verbose then
- lba_log("x : "..turtlePosition.x.." - y : "..turtlePosition.y.." - z : "..turtlePosition.z.." - o : "..turtleDirection, 3);
- end
- return turtlePosition
- end
- function lba_log(message, level, delay)
- --@params message String Message to display
- -- level Number LogLevel for the message (see parameters section)
- -- delay Number Time to wait after display in seconds
- level = level or 4
- delay = delay or (4-level)*0.33
- local levelMessage = ""
- -- Manage turtle term display
- if(level <= logTermLevel) then
- if level == 1 then
- levelMessage = "!ERR : "
- elseif level == 2 then
- levelMessage = "Warn : "
- elseif level == 3 then
- levelMessage = "Info : "
- else
- levelMessage = "Verb : "
- end
- -- Formatting message based on screen size
- local w, h = term.getSize()
- local maxLen = w - string.len(levelMessage)
- local i = 0
- local line = ""
- for w in string.gmatch(message, "[%w%p]+%s?") do
- if (i + string.len(w)) > maxLen then
- print(levelMessage,line)
- line = ""
- i = 0
- levelMessage = " "
- end
- line = line..w
- i = i + string.len(w)
- end
- print(levelMessage,line)
- sleep(delay)
- end
- -- Manage rednet broadcast messages
- -- TODO
- end
- function lba_getSlotContent(slotNumber)
- --@input slot Number Slot to be examined
- --@return String ItemName@damageValue, false if slot empty
- local m = turtle.getItemDetail(slotNumber)
- local ret = false
- if m then
- ret = string.match(m.name,"minecraft:(.+)")
- ret = ret.."@"
- ret = ret..m.damage
- end
- return ret
- end
- -----------------------------------------------------------------------------
- -- MOVEMENT AND ORIENTATION FUNCTIONS
- -----------------------------------------------------------------------------
- -- @function left turn turtle left
- -- @function right turn turtle right
- -- @function faceTo change turtle orientation to the provided angle
- -- @function forward move turtle forward and update its position
- -- @function up move turtle up and update its position
- -- @function down move turtle down and update its position
- -- @function goTo move turtle to given coordinates
- function left()
- --@ return true
- if turtle.turnLeft() then
- turtleDirection = turtleDirection + 90
- if turtleDirection == 360 then
- turtleDirection = 0
- end
- end
- return true
- end
- function right()
- --@ return true
- if turtle.turnRight() then
- turtleDirection = turtleDirection - 90
- if turtleDirection == -90 then
- turtleDirection = 270
- end
- end
- return true
- end
- function faceTo(angle)
- --@params angle angle choosen between 0, 90, 180, 270
- --@ return true
- if angle ~= turtleDirection then
- local mod = (angle-turtleDirection)%360
- if mod == 180 then
- left()
- left()
- elseif mod == 90 then
- left()
- elseif mod == 270 then
- right()
- end
- end
- return true
- end
- function forward(n)
- -- @params n (optional) Number of blocks to go
- -- @return true turtle moved all the way
- -- false turtle didn't move all the way
- n = n or 1
- for i=1,n do
- if (turtleStates.isGoingForFuel == false) and autoRefuelEnabled then
- checkIfRefuelNeeded()
- end
- if turtle.getFuelLevel() == 0 then
- waitForRefuel()
- end
- local xi, zi = 0
- local moved = false
- local tries = 1
- while (not moved) and (tries <= maxTries) do
- if turtle.forward() then
- moved = true
- else
- if autoDig then turtle.dig() end
- if autoAttack then turtle.attack() end
- if turtle.forward() then
- moved = true
- else
- tries = tries + 1
- if(tries <= maxTries) then
- lba_log("Failed to move forward. Trying again", 2)
- else
- lba_log("Error moving forward. Entering idle mode", 1)
- turtleStates['isOnError'] = true
- turtleStates['isStuck'] = true
- end
- end
- end
- end
- if moved then
- if turtleDirection == 0 then
- xi = 1
- zi = 0
- elseif turtleDirection == 90 then
- xi = 0
- zi = -1
- elseif turtleDirection == 180 then
- xi = -1
- zi = 0
- elseif turtleDirection == 270 then
- xi = 0
- zi = 1
- end
- local move = vector.new(xi, 0, zi)
- turtlePosition = turtlePosition + move
- else
- return false
- end
- end
- return true
- end
- function up(n)
- -- @params n Number of blocks to go
- -- @return true Turtle moved up
- -- false Turtle didn't move
- n = n or 1
- for i=1,n do
- if (turtleStates.isGoingForFuel == false) and autoRefuelEnabled then
- checkIfRefuelNeeded()
- end
- if turtle.getFuelLevel() == 0 then
- waitForRefuel()
- end
- local moved = false
- local tries = 1
- while (not moved) and (tries <= maxTries) do
- if turtle.up() then
- moved = true
- else
- if autoDig then turtle.digUp() end
- if autoAttack then turtle.attackUp() end
- if turtle.up() then
- moved = true
- else
- tries = tries + 1
- if(tries < maxTries) then
- lba_log("Failed to move up. Trying again", 2)
- else
- lba_log("Error moving up. Entering idle mode", 1)
- turtleStates['isOnError'] = true
- turtleStates['isStuck'] = true
- end
- end
- end
- end
- if moved then
- turtlePosition.y = turtlePosition.y + 1
- else
- return false
- end
- end
- return true
- end
- function down(n)
- -- @params n Number of blocks to go
- -- @return true Turtle moved up
- -- false Turtle didn't move
- n = n or 1
- for i=1,n do
- if (turtleStates.isGoingForFuel == false) and autoRefuelEnabled then
- checkIfRefuelNeeded()
- end
- if turtle.getFuelLevel() == 0 then
- waitForRefuel()
- end
- local moved = false
- local tries = 1
- while (not moved) and (tries <= maxTries) do
- if turtle.down() then
- moved = true
- else
- if autoDig then turtle.digDown() end
- if autoAttack then turtle.attackDown() end
- if turtle.down() then
- moved = true
- else
- tries = tries + 1
- if(tries < maxTries) then
- lba_log("Failed to move down. Trying again", 2)
- else
- lba_log("Error moving down. Entering idle mode", 1)
- turtleStates['isOnError'] = true
- turtleStates['isStuck'] = true
- end
- end
- end
- end
- if moved then
- turtlePosition.y = turtlePosition.y - 1
- else
- return false
- end
- end
- return true
- end
- function goTo(x, y, z)
- -- Generic function for moving to a distant position
- local xi = x - turtlePosition.x
- local yi = y - turtlePosition.y
- local zi = z - turtlePosition.z
- local function moveX(xi)
- if xi > 0 then
- faceTo(0)
- elseif xi < 0 then
- faceTo(180)
- end
- forward(math.abs(xi))
- end
- local function moveZ(zi)
- if zi > 0 then
- faceTo(270)
- elseif zi < 0 then
- faceTo(90)
- end
- forward(math.abs(zi))
- end
- if yi > 0 then
- up(yi)
- moveX(xi)
- moveZ(zi)
- else
- moveX(xi)
- moveZ(zi)
- down(-yi)
- end
- end
- -----------------------------------------------------------------------------
- -- FUEL RELATED FUNCTIONS
- -----------------------------------------------------------------------------
- --@Function waitForRefuel Enters turtle in error mode til refueling
- --@function distanceToFuel Returns distance (in blocks) to fuel supply and triggers autoRefuel if set
- function waitForRefuel()
- --@return Boolean Wait for user provide some fuel
- turtleStates.isFuelShortage = true
- turtleStates.isOnError = true
- lba_log("I'm in error. Please provide some fuel in slot "..fuelSlot,1)
- turtle.select(fuelSlot)
- while true do
- local event = os.pullEvent("turtle_inventory")
- if turtle.refuel() then
- lba_log("Refueled. Going back to work",3)
- turtleStates.isFuelShortage = false
- turtleStates.isOnError = false
- break
- else
- lba_log("My inventory changed but I can't find any fuel in slot "..fuelSlot,2);
- end
- end
- end
- function distanceToFuel()
- --@return Number Distance to fuel supply
- local vf = vector.new(0,0,0)
- local distance = 0
- if turtleStates.isScanningMaterialArea or turtleStates.isGoingForMaterials then
- -- Restricted cases, turtle must exit area by the start point, then going to start position before going for fuel for hoping to avoid containers
- -- Therefore, distance is higher ^^
- vf = autoDetectStartPosition - turtlePosition
- distance = math.abs(vf.x) + math.abs(vf.y) + math.abs(vf.z)
- vf = vf + startPosition - autoDetectStartPosition
- distance = distance + math.abs(vf.x) + math.abs(vf.y) + math.abs(vf.z)
- vf = vf + fuelPosition - startPosition
- distance = distance + math.abs(vf.x) + math.abs(vf.y) + math.abs(vf.z)
- else
- vf = fuelPosition - turtlePosition
- distance = math.abs(vf.x) + math.abs(vf.y) + math.abs(vf.z)
- end
- return distance
- end
- function checkIfRefuelNeeded()
- --@return Boolean True if fuel needed, false if not
- local distance = distanceToFuel() + 1
- if turtle.getFuelLevel() <= distance then
- if autoRefuelEnabled then
- goRefuel()
- return false
- else
- waitForRefuel()
- return true
- end
- end
- end
- function goRefuel()
- --@return Number Fuel Level
- lba_log("I'm leaving work for refueling",3)
- turtleStates.isGoingForFuel = true
- --Sauvegarde de la position
- local xs = turtlePosition.x
- local ys = turtlePosition.y
- local zs = turtlePosition.z
- --Fuel Slot cleaning in case of previous mining/digging
- turtle.select(fuelSlot)
- if turtle.getItemCount(fuelSlot) > 0 then turtle.dropDown() end
- goTo(fuelPosition.x, fuelPosition.y, fuelPosition.z)
- -- Refueling
- while(turtle.getFuelLevel() < turtle.getFuelLimit()) do
- -- Orients turtle to fuel storage
- if math.abs(autoRefuelSuckDirection) > 1 then
- faceTo(autoRefuelSuckDirection)
- turtle.suck(1)
- elseif autoRefuelSuckDirection == 1 then
- turtle.suckUp(1)
- else
- turtle.suckDown(1)
- end
- if not(turtle.refuel()) then
- lba_log("Sorry. Can't refuel, please check fuel storage and refuel me in manual mode",1)
- waitForRefuel()
- end
- lba_log("Refueling "..turtle.getFuelLevel().."/"..turtle.getFuelLimit(),4)
- if turtle.getItemDetail() then
- lba_log("Throwing garbage",4)
- if math.abs(autoRefuelDropDirection) > 1 then
- faceTo(autoRefuelDropDirection)
- turtle.drop(1)
- elseif autoRefuelDropDirection == 1 then
- turtle.dropUp(1)
- else
- turtle.dropDown(1)
- end
- end
- end
- lba_log("Refueled! Going back to work",3)
- turtleStates.isGoingForFuel = false
- goTo(xs, ys, zs)
- end
- -----------------------------------------------------------------------------
- -- MATERIALS RELATED FUNCTIONS
- -----------------------------------------------------------------------------
- function waitForMaterials(material)
- --@param material String Material needed
- --@return Boolean Wait for user provide some materials
- turtleStates.isMaterialShortage = true
- turtleStates.isOnError = true
- lba_log("In on error. Please provide me "..material.." to build more",1)
- local waiting = true
- while waiting do
- local event, p1 = os.pullEvent("turtle_inventory")
- for i=1,16 do
- local m = lba_getSlotContent(i)
- if m then
- if m == material then
- lba_log("Refilled "..material..". Going back to work",3)
- turtleStates.isMaterialShortage = false
- turtleStates.isOnError = false
- waiting = false
- else
- lba_log("My inventory changed but I can't find "..material.." in any slot",2);
- end
- end
- end
- end
- end
- function scanMaterialsArea()
- --@return nil
- -- Looking for the turtle direction for optimizing detection
- local scanOrder
- local way = vector.new(0,0,0)
- local wayToGo = vector.new(0,0,0)
- local xn = 0
- local yn = 0
- local zn = 0
- way = autoDetectEndPosition - autoDetectStartPosition
- if not(way.x == 0) then -- Scanning top, bottom, zleft, zright
- scanOrder = {1, -1, 90, 270}
- xn = (autoDetectEndPosition.x - autoDetectStartPosition.x)/math.abs(autoDetectEndPosition.x - autoDetectStartPosition.x)
- elseif not(way.z == 0) then -- Scanning top, bottom, xleft, xright
- scanOrder = {1, -1, 0, 180}
- zn = (autoDetectEndPosition.z - autoDetectStartPosition.z)/math.abs(autoDetectEndPosition.z - autoDetectStartPosition.z)
- elseif not(way.y == 0) then -- Scanning xleft, xright, zleft, zright
- scanOrder = {0, 90, 180, 270}
- yn = (autoDetectEndPosition.y - autoDetectStartPosition.y)/math.abs(autoDetectEndPosition.y - autoDetectStartPosition.y)
- elseif (way.x == 0) and (way.y == 0) and (way.z == 0) then -- One single position for storage area
- scanOrder = {1, -1, 0, 90, 180, 270}
- else
- lba_log("Unable to find my way in the storage area. Did you really set a straight line ?",1)
- return false
- end
- -- Starting autoDetection
- turtleStates.isScanningMaterialArea = true
- goTo(autoDetectStartPosition.x, autoDetectStartPosition.y, autoDetectStartPosition.z)
- repeat
- wayToGo = autoDetectEndPosition - turtlePosition
- for k, d in pairs(scanOrder) do
- doScanContainer(d)
- end
- goTo(turtlePosition.x + xn, turtlePosition.y + yn, turtlePosition.z + zn)
- until wayToGo:length() == 0
- turtleStates.isScanningMaterialArea = false
- return true
- end
- function doScanContainer(direction)
- --@params direction Number Direction to do Scan
- --@return nil
- local function addItemToMaterialList(direction)
- local m = lba_getSlotContent(fuelSlot)
- lba_log("Found "..m.." at "..direction,4)
- registeredMaterials = registeredMaterials+1
- if(materialLocation[m]) then
- materialLocation[m].x = turtlePosition.x
- materialLocation[m].y = turtlePosition.y
- materialLocation[m].z = turtlePosition.z
- materialLocation[m].d = direction
- if(materialLocation[m].locked) then -- Remplissage des solts réservés à ce matériel
- lba_log("Found locked slot(s) for "..m, 4)
- for i, slot in ipairs(materialLocation[m].locked) do fillSlot(m, slot) end
- turtle.select(fuelSlot)
- end
- else
- materialLocation[m] = {x = turtlePosition.x, y = turtlePosition.y, z = turtlePosition.z, d = direction}
- end
- end
- lba_log("Starting location scan at "..direction,4)
- turtle.select(fuelSlot)
- if direction == 1 then
- if turtle.suckUp(1) then
- addItemToMaterialList(1)
- turtle.dropUp()
- end
- elseif direction == -1 then
- if turtle.suckDown(1) then
- addItemToMaterialList(-1)
- turtle.dropDown()
- end
- else
- faceTo(direction)
- if turtle.suck(1) then
- addItemToMaterialList(direction)
- turtle.drop()
- end
- end
- end
- function fillSlot(m, slot)
- local ret = false
- lba_log("Filling slot "..slot.." with "..m,4)
- turtle.select(slot)
- local toSuck = 64 - turtle.getItemCount()
- if materialLocation[m].d == 1 then
- ret = turtle.suckUp(toSuck)
- elseif materialLocation[m].d == -1 then
- ret = turtle.suckDown(toSuck)
- else
- faceTo(materialLocation[m].d)
- ret = turtle.suck(toSuck)
- end
- return ret
- end
- function emptySlot(m, slot)
- local ret = false
- lba_log("Emptying slot "..slot.." containing "..m,4)
- turtle.select(slot)
- local toDrop = turtle.getItemCount()
- if materialLocation[m].d == 1 then
- ret = turtle.dropUp(toDrop)
- elseif materialLocation[m].d == -1 then
- ret = turtle.dropDown(toDrop)
- else
- faceTo(materialLocation[m].d)
- ret = turtle.drop(toDrop)
- end
- return ret
- end
- function goRefill(m)
- --@params m string material to fetch
- --Position record
- local xs = turtlePosition.x
- local ys = turtlePosition.y
- local zs = turtlePosition.z
- local shipped = false
- lba_log("I'm leaving work for refilling "..m, 3)
- turtleStates.isGoingForMaterials = true
- goTo(autoDetectStartPosition.x, autoDetectStartPosition.y, autoDetectStartPosition.z)
- if not(materialLocation[m].locked) then
- -- Emptying inventory first when not using locked slots
- for i = 1, 16 do
- if i~=fuelSlot then
- turtle.select(i)
- cm = lba_getSlotContent(i)
- if(cm) then
- goTo(materialLocation[cm].x, materialLocation[cm].y, materialLocation[cm].z)
- emptySlot(cm,i)
- end
- end
- end
- end
- -- Refilling
- goTo(materialLocation[m].x, materialLocation[m].y, materialLocation[m].z)
- local slotsToFill = {}
- if not(materialLocation[m].locked) then
- for i = 1, 16 do
- if i~=fuelSlot then
- table.insert(slotsToFill,i)
- end
- end
- else
- slotsToFill = materialLocation[m].locked
- end
- for i, slot in pairs(slotsToFill) do
- if fillSlot(m, slot) then shipped = true end
- end
- if not(shipped) then waitForMaterials(m) end
- lba_log("Materials shipped. Going back to Work")
- goTo(autoDetectEndPosition.x, autoDetectEndPosition.y, autoDetectEndPosition.z)
- turtleStates.isGoingForMaterials = false
- goTo(xs, ys, zs)
- end
- -----------------------------------------------------------------------------
- -- BUILDING RELATED FUNCTIONS
- -----------------------------------------------------------------------------
- function placeBlock(m)
- --@params m string Material to be placed
- --@return boolean True if placed
- -- Check for material in inventory
- local hasMaterials = false
- if(materialLocation[m].locked) then
- for i, slot in pairs(materialLocation[m].locked) do
- if turtle.getItemCount(slot) > 1 then
- turtle.select(slot)
- hasMaterials = true
- break
- end
- end
- else
- local cm = lba_getSlotContent(turtle.getSelectedSlot())
- if cm == m then
- hasMaterials = true
- else
- for i=1,16 do
- cm = lba_getSlotContent(i)
- if cm == m then
- turtle.select(i)
- hasMaterials = true
- end
- end
- end
- end
- if not(hasMaterials) and autoRefillEnabled then goRefill(m)
- elseif not(hasMaterials) then waitForMaterials(m) end
- if(turtle.placeDown()) then
- totalBlocks = totalBlocks + 1
- return true
- else -- Try to remove that prevents block placing
- if autoDig then turtle.digDown() end
- if autoAttack then turtle.attackDown() end
- if(turtle.placeDown()) then
- totalBlocks = totalBlocks + 1
- return true
- end
- end
- end
- function dot(x, y, z, m)
- --@params x, y, z Number Coordinates
- -- m String Material to be used
- --@return nil
- turtleStates.isBuilding = true
- goTo(x, y+1, z)
- placeBlock(m)
- turtleStates.isBuilding = false
- end
- function line(x1, y1, z1, x2, y2, z2, m)
- --@params x1, y1, z1 Number Start coordinates
- -- x2, y2, z2 Number End coordinates
- -- m String Material to be used
- --@return nil
- if (y2 < y1) then
- local c = x2
- x2 = x1
- x1 = c
- c = y2
- y2 = y1
- y1 = c
- c = z2
- z1 = c
- end
- turtleStates.isBuilding = true
- tx = math.abs(x2-x1)
- ty = math.abs(y2-y1)
- tz = math.abs(z2-z1)
- tmax = math.max(tx,ty,tz)
- if tmax == 0 then dot(x1, y1, z1, m) end -- It's a dot, not a line
- for t=0, tmax do
- local x = math.floor((x2-x1)*t/tmax + x1 + 0.5)
- local y = math.floor((y2-y1)*t/tmax + y1 + 1.5)
- local z = math.floor((z2-z1)*t/tmax + z1 + 0.5)
- goTo(x,y,z)
- placeBlock(m)
- end
- turtleStates.isBuilding = false
- end
- function rectangleY (x1, z1, x2, z2, y, m, filled, thickness)
- --@params x1, z1 Number Start coordinates
- -- x2, z2 Number End coordinates
- -- y Number Rectangle height
- -- m String Material to be used
- -- filled Boolean Filled rectangle
- -- thickness Number Border width if not filled
- --@return nil
- filled = filled or false
- thickness = thickness or 1
- turtleStates.isBuilding = true
- --Shortest start point
- local dTo1 = turtlePosition - vector.new(x1,y1,z1)
- local dTo2 = turtlePosition - vector.new(x2,y2,z2)
- if dTo1:length() <= dTo2:length() then
- xs = x1
- zs = z1
- xe = x2
- ze = z2
- else
- xs = x2
- zs = z2
- xe = x1
- ze = z1
- end
- local ix = (xe-xs)/math.abs(xe-xs)
- local iz = (ze-zs)/math.abs(ze-zs)
- local n=1
- local checkUneven = false
- if filled then
- n = math.floor(math.min(math.abs(xe-xs),math.abs(ze-zs))/2) - 1
- checkUneven = true
- else
- n = thickness - 1
- end
- for i=0, n do
- line(xs+i*ix, y, zs+i*iz, xe-(i+1)*ix, y, zs+i*iz, m)
- line(xe-i*ix, y, zs+i*iz, xe-i*ix, y, ze-(i+1)*iz, m)
- line(xe-i*ix, y, ze-i*iz, xs+(i+1)*ix, y, ze-i*iz, m)
- line(xs+i*ix, y, ze-i*iz, xs+i*ix, y, zs+(i+1)*iz, m)
- if (i==n) and checkUneven then -- Case of uneven shortest side size
- if ((xe-xs)<=(ze-zs)) and not((xe-xs+1)%2==0) then
- if (zs+(i+1)*iz) == (ze-(i+1)*iz) then -- One dot for finish when square
- dot(xs+(i+1)*ix, y, zs+(i+1)*iz, m)
- else -- line to finish
- line(xs+(i+1)*ix, y, zs+(i+1)*iz, xs+(i+1)*ix, y, ze-(i+1)*iz, m)
- end
- elseif ((xe-xs)>(ze-zs)) and not((ze-zs+1)%2==0) then
- line(xs+(i+1)*ix, y, zs+(i+1)*iz, xe-(i+1)*ix, y, zs+(i+1)*iz, m)
- end
- end
- end
- end
- function xmobFloor(x1, z1, x2, z2, y, m)
- --@params x, z Number Starting point coordinates
- -- z Number Height
- -- m String Material to be used
- local xt = x1 + (x2-x1)/2; -- Horizontal offset for computing
- local zt = z1 + (z2-z1)/2; -- vertical offset for computing
- local startx = 0
- local endx = 0
- local incrementx = 0
- local b = 0
- goTo(x1,y+1,z1)
- for zi = z1, z2 do
- if turtlePosition.x == x1 then
- startx = x1
- endx = x2
- incrementx = 1
- else
- startx = x2
- endx = x1
- incrementx = -1
- end
- for xi = startx, endx, incrementx do
- goTo(xi,y+1,zi)
- -- Calculator for x-shape
- b = math.abs(math.abs(zi-zt)-math.abs(xi-xt))
- if b >= 3 then placeBlock(m) end
- end
- end
- end
- lba_initialize()
- lba_yourBuild()
- lba_end()
Add Comment
Please, Sign In to add comment