Advertisement
theinsekt

enclosed tree farm

Mar 12th, 2015
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 17.09 KB | None | 0 0
  1. --pastebin get nLNQiU0W theinsektAPIs/treefarm1
  2. -- see ziBBd33L for startup program and installation instructions
  3. --not working, experimental, not tested
  4. --will plant in middle of room.
  5. --the outputChest should be in the floor,
  6. --adjacent to a wall, and intersected by a straight line from the middle of the room.
  7. --Should be able to handle being restarted at any point in the program
  8. --except maybe the first time if interrupted while writing to file.
  9.  
  10. --position zero is above output chest facing inwards
  11.  
  12. --todo: roof, walls and corners at bottom must be walltype
  13. --
  14.  
  15. os.loadAPI("theinsektAPIs/fileHelp")
  16. os.loadAPI("theinsektAPIs/poz3")
  17. os.loadAPI("theinsektAPIs/poz3a")
  18.  
  19. function treeFarm(wallBlocks,limit)
  20. --emptyInventory("d", {["minecraft:sapling"]=2,})--debug
  21. --do return end
  22.  
  23. --if this is the first time, or if there was an error before
  24. --print usage instructions
  25. local startStuffPath="configs/startStuff"
  26. local startString=fileHelp.loadString(startStuffPath)
  27. if startString~="skip" then
  28.   if startString==nil then startString="first" end
  29.   if startString=="first" then
  30.     print("Place this turtle in an enclosed room, with the width in both directions being odd (5 ,7 etc.).")
  31.     print("Put one or more saplings in inventory slot 1, in the turtle.")
  32.     print("Put an output chest in the middle along one of the walls, in the floor.")
  33.     print("Put a fuel chest 2 steps to the left (if looking towards middle from output chest).")
  34.     print("Put a dirt block in middle of the floor.")
  35.   else
  36.     print("Previously quit with error:")
  37.     print(startString)
  38.   end
  39.   print("Press: c continue, e exit,i instructions, r reset configs, u update.")
  40.  
  41.   --wait for key press
  42.   local _, key =os.pullEvent("key")
  43.   --clear terminal
  44.   --term.clear()
  45.   --term.setCursorPos(1,1)
  46.  
  47.   if key==keys.c then
  48.     print("continuing...")
  49.     fileHelp.saveString(startStuffPath,"skip")
  50.   elseif key==keys.e then
  51.     print("Exiting...")
  52.     return
  53.   elseif key==keys.i then
  54.     fileHelp.saveString(startStuffPath,"first")
  55.     os.reboot()
  56.   elseif key==keys.r then
  57.     clearConfigs()
  58.     fileHelp.saveString(startStuffPath,"first")
  59.     os.reboot()
  60.   else--
  61.     print("Choice not yet implemented, terminating")
  62.     return
  63.   end
  64. end--if
  65. treeFarmStates(wallBlocks,limit)
  66. end--function
  67.  
  68. --wallblocks is a table like this {"minecraft:cobblestone"=true, "minecraft:glass"=true, "minecraft"}
  69. function treeFarmStates(wallBlocks,limit)
  70. --state: start
  71. print("debug, state: start")
  72. --will save stuff like plantName and dimensions,
  73. --so that it can be loaded after next restart
  74. --local tryLoad=true
  75. --local trySave=true
  76.  
  77. --state: getting plantName
  78. print("debug, state: getting plantName")
  79. --get type of plant (from file or slot 1)
  80. local plantName = getItemType(1,"configs/plantName")
  81. if plantName==nil then
  82.   quitWithError("Error: No plant in slot 1")
  83. end
  84.  
  85. ----(skipped)state: getting fuelName
  86. --get type of fuel (from file or slot 2)
  87. --local fuelName = getItemType(2,"configs/fuelName")
  88.  
  89. --state: getting room dimensions, get dimensions of room (from file or program)
  90. print("debug, state: getting room dimensions")
  91. local dimensions=getDimensions(wallBlocks, limit,"configs/dimensions")
  92. local halfWidth=math.floor(dimensions["width"]/2)
  93.  
  94. --state: defining coordinate points, now it's possible to define some coordinates
  95. print("debug, state: defining coordinate points")
  96. --some coords
  97. --positive x=east
  98. --positive y=up
  99. --positive z=south
  100. --north is if standing on output chest and looking towards plant in the middle
  101. local outputChestPos={x=0,y=0,z=0,f="n"}--above output chest, looking towards plant in middle of room
  102. local southWestCorner={x=-halfWidth,y=0,z=0,f="n"}--used as a starting point when harvesting
  103. local waitPos={x=0,y=0,z=-(halfWidth-1),f="n"}--go north from outputChestPos until before plant
  104. local fuelPos={x=-2,y=0,z=0,f="n"}--two steps to the left of output chest
  105.  
  106. --state: defining keep table
  107. print("debug, state: defining keep table")
  108. --what items to keep when emptying the inventory, and how much
  109. --local keepTable={[plantName]=32,[fuelName]=32}
  110. local keepTable={[plantName]=32,}
  111.  
  112.  
  113.  
  114. --state: finding pos
  115. print("debug, state: finding pos")
  116. findAndSetPos(dimensions, plantName, wallBlocks,waitPos,outputChestPos)
  117.  
  118.  
  119. while(true) do
  120.   --state: refuelling
  121.   print("debug, state: refueling")
  122.   --refuel if has to little fuel
  123.   gotoAndRefuelFromChestIf(fuelPos, "d",1000,2000)
  124.   --state: waiting
  125.   print("debug, state: waiting")
  126.   --wait until not plant
  127.   while(true) do
  128.     --get what is infront
  129.     local success, data=poz3.inspect("n")
  130.     if not success then
  131.       --plant has somehow disappeared, so goto next state
  132.       break
  133.     end
  134.     if success and data.name~=plantName then
  135.       --it's a tree, or the wrong plant, so goto next state
  136.       break
  137.     end
  138.     --the sappling is still there so wait for a while
  139.     os.sleep(10)
  140.   end
  141.   --state: destroying plant position
  142.   print("debug, state: destroying plant position")
  143.   --dig if it's not a wall
  144.   if not isBlockMatch("n", wallBlocks) then
  145.     poz3.dig("n")
  146.   end
  147.   --state: harvesting/clearing (destroy not plant and not wall, then dcube2 inside room)
  148.   print("debug, state: harvesting/clearing")
  149.   harvest(dimensions, southWestCorner)
  150.   --state: emptying inventory
  151.   print("debug, state: emptying inventory")
  152.   if not poz3a.digToCoords2(outputChestPos) then
  153.     quitWithError("Error: failed when trying to go to output chest.")
  154.   end
  155.   emptyInventory("d", keepTable)
  156.   --state: planting
  157.   print("debug, state: planting")
  158.   --goto plant/wait position
  159.   if not poz3a.digToCoords2(waitPos) then
  160.     quitWithError("Error: failed when trying to go to wait position (infront of plant).")
  161.   end
  162.   --place/plant sapling
  163.   if not placeItem("n",plantName) then
  164.     quitWithError("Error: failed when trying to place sapling.")
  165.   end
  166. end
  167. end--main
  168.  
  169. function gotoAndRefuelFromChestIf(fuelPos, direction,lower,upper)
  170.   --check if fuel level is below lower limit
  171.   local fuelLevel=turtle.getFuelLevel()
  172.   --quit if doesnโ€™t need to refuel (fuel level isn't below lower)
  173.   local fuelLevel=turtle.getFuelLevel()
  174.   if fuelLevel == "unlimited" or fuelLevel >= lower then
  175.     return
  176.   end
  177.   --goto refuelling chest
  178.   if not poz3a.digToCoords2(fuelPos) then
  179.     quitWithError("Error: failed when trying to go to refuelling position.")
  180.   end
  181.   --refuel from chest
  182.   if not refuelFromChest(direction, upper) then
  183.     quitWithError("Error: failed when refuelling from chest.")
  184.   end
  185. end
  186.  
  187. --suck fuel from a chest in the given direction
  188. --and refuel until fuel level reaches upper (upper bound)
  189. function refuelFromChest(direction,upper)
  190.   --return true if has unlimited fuel
  191.   if turtle.getFuelLevel() == "unlimited" then return true end
  192.   --check upper
  193.   if upper>turtle.getFuelLimit() then upper=turtle.getFuelLimit() end
  194.   --select the slot to place the fuel in
  195.   local slot=findEmptyInventorySlot()
  196.   if slot==-1 then
  197.     return false
  198.   end
  199.   turtle.select(slot)
  200.   --refuel from chest
  201.   while(turtle.getFuelLevel()<upper) do
  202.     if not poz3.suck(direction,1) then
  203.       --could not suck fuel from fuel chest
  204.       return false
  205.     end
  206.     if not turtle.refuel() then
  207.       --could not refuel from the selected slot
  208.       --maybe it's not a fuel
  209.       return false
  210.     end
  211.   end
  212.   --refuelled!
  213.   return true
  214. end
  215.  
  216. function findEmptyInventorySlot()
  217.   for slot=1,16 do
  218.     if turtle.getItemCount(slot)==0 then
  219.       return slot
  220.     end
  221.   end
  222.   return -1
  223. end
  224.  
  225.  
  226. function placeItem(direction, itemName)
  227.   local slot=getItemSlot(itemName)
  228.   if slot==-1 then return false end
  229.   turtle.select(slot)
  230.   return poz3.place(direction)
  231. end
  232.  
  233. function getItemSlot(itemName)
  234.   for slot=1, 16 do
  235.     local data=turtle.getItemDetail(slot)
  236.     if data and data.name==itemName then
  237.       return slot
  238.     end
  239.   end
  240.   return -1
  241. end
  242.  
  243.  
  244. --not tested
  245. --example keepTable: {"minecraft:sappling"=32,"minecraft:charcoal"=32}
  246. function emptyInventory(direction, keepTable)
  247.   local amounts={}
  248.   for slot=1, 16 do
  249.     local data=turtle.getItemDetail(slot)
  250.     if data then
  251.       if keepTable[data.name] then
  252.         if not amounts[data.name] then amounts[data.name]=0 end
  253.         local limit=keepTable[data.name]
  254.         amount = turtle.getItemCount(slot) + amounts[data.name]
  255.         if amount>limit then
  256.           local dropAmount=amount-limit
  257.           turtle.select(slot)
  258.           poz3.drop(direction,dropAmount)
  259.           amount=limit
  260.         end --if amount>limit
  261.         amounts[data.name]=amount
  262.       else --if keep
  263.         --drop whole stack
  264.         turtle.select(slot)
  265.         poz3.drop(direction)
  266.       end
  267.     end--if data
  268.   end --for
  269.   return true
  270. end
  271.  
  272. function harvest(dimensions, southWestCorner)
  273.   --go to southwest corner
  274.   if not poz3a.digToCoords2(southWestCorner) then
  275.     quitWithError("Error: failed when trying to go to southWestCorner.")
  276.   end
  277.   --harvest, digcube ,refuel=false, return to origin=true
  278.   if not poz3a.callDigCube("u",dimensions["height"],"e",dimensions["width"],"n",dimensions["width"],false,true) then
  279.     quitWithError("Error: failed when digging everything inside the room.")
  280.   end
  281.   --returned to south west corner
  282. end
  283.  
  284.  
  285.  
  286. --does not need a known postion
  287. function getDimensions(wallBlocks,limit, path)
  288.   local dimensions=nil
  289.  
  290.   if path then
  291.     dimensions = fileHelp.loadValue(path)
  292.     if dimensions~=nil then return dimensions end
  293.   end
  294.  
  295.   --measure dimensions
  296.   --go to a top corner
  297.   local len1,data=digGoUntilWall("u",wallBlocks,limit)
  298.   if turtle.getFuelLevel() == 0 then quitWithError("Turtle error: turtle is out of fuel.") end
  299.   if not data then quitWithError("Room error: reached limit without finding a wall block.") end
  300.  
  301.   local len2,data=digGoUntilWall("w",wallBlocks,limit)
  302.   if turtle.getFuelLevel() == 0 then quitWithError("Turtle error: turtle is out of fuel.") end
  303.   if not data then quitWithError("Room error: reached limit without finding a wall block.") end
  304.  
  305.  
  306.   local len3,data=digGoUntilWall("s",wallBlocks,limit)
  307.   if turtle.getFuelLevel() == 0 then quitWithError("Turtle error: turtle is out of fuel.") end
  308.   if not data then quitWithError("Room error: reached limit without finding a wall block.") end
  309.  
  310.  
  311.   --measure height
  312.   local height,data=digGoUntilWall("d",wallBlocks,limit)
  313.   height=height+1--because needs to count place where turtle stood
  314.   if turtle.getFuelLevel() == 0 then quitWithError("Turtle error: turtle is out of fuel.") end
  315.   if not data then quitWithError("Room error: reached limit without finding a wall block.") end
  316.  
  317.  
  318.   if height<2 then error("Room error: the room must have a height that is 2 or larger.") end
  319.  
  320.   --measure width1
  321.   local width1,data=digGoUntilWall("e",wallBlocks,limit)
  322.   width1=width1+1--because needs to count place where turtle stood
  323.   if turtle.getFuelLevel() == 0 then quitWithError("Turtle error: turtle is out of fuel.") end
  324.   if not data then quitWithError("Room error: reached limit without finding a wall block.") end
  325.  
  326.   if width1<5 then
  327.     quitWithError("Room error: the width of the room must be 5 or larger.")
  328.   end
  329.  
  330.   if (width1 % 2) == 0 then
  331.     if not data then
  332.       quitWithError("Room error: the width of the room must be odd number, examples 5 ,7, 9 etc.")
  333.     end
  334.   end
  335.  
  336.  
  337.   --measure width2
  338.   local width2,data=digGoUntilWall("n",wallBlocks,limit)
  339.   width2=width2+1--because needs to count place where turtle stood
  340.   if turtle.getFuelLevel() == 0 then quitWithError("Turtle error: turtle is out of fuel.") end
  341.   if not data then quitWithError("Room error: reached limit without finding a wall block.") end
  342.  
  343.  
  344.   if width1 ~= width2 then quitWithError("Room error: width1 and width2 must be the same in the room.") end
  345.  
  346.   --save and return dimensions
  347.   dimensions={["width"]=width1, ["height"]=height,}
  348.   if path then
  349.     fileHelp.saveValue(path,dimensions)
  350.   end
  351.   return dimensions
  352. end
  353.  
  354. --returns true if should be waiting
  355. --returns false if should be harvesting
  356. function findAndSetPos(dimensions, plantName, wallBlocks,waitPos,outputChestPos)
  357.   local success,data=poz3.inspect("f")
  358.   if success then
  359.     if data.name==plantName then
  360.       --known pos, at waitpos
  361.       print("debug, pos: waitPos")
  362.       poz3.setPos2(waitPos)
  363.       return
  364.     end --if
  365.     --if it's not a wall it might be
  366.     --a sapling of wrong type so destroy it
  367.     if not wallBlocks[data.name] then
  368.       print("removing potential bad plant")
  369.       poz3.dig("f")
  370.     end
  371.   end --if
  372.  
  373.   --unknown pos, so find it
  374.   local halfWidth=math.floor(dimensions["width"]/2)
  375.   findOutputChest(dimensions,halfWidth,wallBlocks)
  376.   print("debug, pos: outputChestPos")
  377.   poz3.setPos2(outputChestPos)
  378. end --function
  379.  
  380. --Goes to the outputChestPos without knowing the current position
  381. function findOutputChest(dimensions,halfWidth,wallBlocks)
  382.   --go to a top corner
  383.   local _,data=digGoUntilWall("u",wallBlocks,dimensions["height"])
  384.   if data==nil then quitWithError("Room error: a wall is missing, or dimensions have changed") end
  385.   local _,data=digGoUntilWall("w",wallBlocks,dimensions["width"])
  386.   if data==nil then quitWithError("Room error: a wall is missing, or dimensions have changed") end
  387.   local _,data=digGoUntilWall("s",wallBlocks,dimensions["width"])
  388.   if data==nil then quitWithError("Room error: a wall is missing, or dimensions have changed") end
  389.  
  390.  
  391.   --go to bottom corner
  392.   local len1,data=digGoUntilWall("d",wallBlocks,dimensions["height"]+1)
  393.   if data==nil then quitWithError("Room error: a wall is missing, or dimensions have changed") end
  394. if len1+1 ~= dimensions["height"] then quitWithError("Room error: a wall is missing, or dimensions have changed") end
  395.  
  396.  
  397.   --go in circle looking for chest,
  398.   local turnDirectionIfFound="l"
  399.   if checkForMiddleChest("e",halfWidth,wallBlocks,turnDirectionIfFound) then return true end
  400.   if checkForMiddleChest("n",halfWidth,wallBlocks,turnDirectionIfFound) then return true end
  401.   if checkForMiddleChest("w",halfWidth,wallBlocks,turnDirectionIfFound) then return true end
  402.   if checkForMiddleChest("s",halfWidth,wallBlocks,turnDirectionIfFound) then return true end
  403.  
  404.   quitWithError("Room error: there is no output chest at the four possible positions, or room dimensions have changed")
  405. end
  406.  
  407. --must be going along right wall
  408. function checkForMiddleChest(direction,halfWidth,wallBlocks,directionIfFound)
  409.   local _,data=digGoUntilWall(direction,wallBlocks,halfWidth)
  410.   if data then quitWithError("Room error: a wall block is inside room, or dimensions have changed") end
  411.   local success, data=poz3.inspect("d")
  412.   if success and data and data.name=="minecraft:chest" then
  413.     poz3.turn(directionIfFound)
  414.     return true
  415.   end
  416.   local _,data=digGoUntilWall(direction,wallBlocks,halfWidth+1)
  417.   if not data then quitWithError("Room error: a wall block is missing, or dimensions have changed") end
  418.   return false
  419. end
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426. --returns blocksTraveled, blockData if encountered a wall
  427. --returns limit, nil if travelled limit blocks
  428. --returns blokcsTraveled, nil if blocked by something undigable (impossible?)
  429. function digGoUntilWall(direction, wallBlocks,limit)
  430.   for i=1, limit do
  431.     local went, data = digGoIfNotWall(direction, wallBlocks)
  432.     if not went then return i-1, data end
  433.   end
  434.   return limit,nil
  435. end
  436.  
  437. --digs or goes one step in the given direction
  438. --returns true,nil if went
  439. --returns false, nil if could not dig through non wall block
  440. --returns false, blockData if reached wall
  441. --will continue trying if blocked by player
  442. function digGoIfNotWall(direction,wallBlocks)
  443.   --no fuel
  444.   if turtle.getFuelLevel() == 0 then return false,nil end
  445.   while(true) do
  446.     --check block in direction
  447.     local success, data=poz3.inspect(direction)
  448.     if success then
  449.       if wallBlocks[data.name] then
  450.         return false, data
  451.       end
  452.       if not poz3.dig(direction) then return false, nil end
  453.     end
  454.     --go in direction
  455.     if poz3.go(direction) then return true, nil end
  456.   end
  457. end
  458.  
  459.  
  460. --resulting direction could be changed
  461. --returns the name of the block, if it's one of the blocks
  462. --blocks could be a string, or a table with string keys
  463. function isBlockMatch(direction, blocks)
  464.   local success, data=poz3.inspect(direction)
  465.   if success then
  466.     if type(blocks)=="string" then
  467.       if data.name=blocks
  468.         return data.name
  469.       end--if
  470.       return nil
  471.     end--if type
  472.     if blocks[data.name]
  473.       return data.name
  474.     end--if
  475.   end--if success
  476.   return nil
  477. end--function
  478.  
  479.  
  480. --first tries to get itemname from the given file path
  481. --second tries to find name of the item in the given slotNum
  482. --if got itemName from slot and doSave is true, then saves the itemName in the given path
  483. function getItemType(slotNum,path)
  484.   local itemName=nil
  485.   if path then
  486.     itemName=fileHelp.loadString(path)
  487.   end
  488.   if itemName==nil then
  489.     local data=turtle.getItemDetail(slotNum)
  490.     if data then
  491.       itemName=data.name
  492.       if path then
  493.         fileHelp.saveString(path,itemName)
  494.       end
  495.     end
  496.   end
  497.   return itemName
  498. end
  499.  
  500. function quitWithError(errorMessage)
  501.   fileHelp.saveString("configs/startStuff",errorMessage)
  502.   error(errorMessage,2)
  503. end
  504.  
  505. function clearConfigs()
  506.   --delete the configs folder
  507.   fs.delete("configs")
  508. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement