kLeeNex24

new turtlex

Jul 27th, 2013
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 29.35 KB | None | 0 0
  1. --DEPENDS REQ:inventory
  2. --[[== turtlex api ====================
  3. high-level alternative to turtle api,
  4. adds position and inventory tracking
  5. with persistance through unloading or
  6. reboot.
  7.  
  8. code by GopherAtl
  9. Do whatever you want with it, just
  10. give me credit, and if you redistribute
  11. please link back to the turtlex thread
  12. on the computercraft forums.
  13. =====================================]]
  14. local native=turtle
  15.  
  16. --[[ as-yet unimplemented
  17. function attack()
  18. function attackUp()
  19. function attackDown()
  20. --]]
  21.  
  22. --[[   internal variables ]]--
  23. local dirMap={north=0, east=1, south=2, west=3}
  24. local dirVMap={}
  25. dirVMap[0]=   vector.new( 0, 0,-1)
  26. dirVMap[1]=   vector.new( 1, 0, 0)
  27. dirVMap[2]=   vector.new( 0, 0, 1)
  28. dirVMap[3]=   vector.new(-1, 0, 0)
  29.  
  30. local position=vector.new(0,0,0)
  31. local direction=0
  32. local selectedSlot = 1
  33. local myInventory=nil
  34. local posStack={}
  35. local lastReportedPos=vector.new(0,0,0)
  36. local monitorId=nil
  37. local hostileMode=false
  38.  
  39. --[[=====  internal methods  ======]]--
  40.  
  41. local function reportPos(msg)
  42.   if monitorId then
  43.     msg = msg or "moved"
  44.     rednet.send(monitorId,"update "..position.x.." "..position.y.." "..position.z.." "..msg)  
  45.     lastReportedPos={x=position.x,y=position.y,z=position.z}
  46.   end
  47. end  
  48.  
  49. local function reportPosIfChanged()
  50.   if monitorId then
  51.     local d=math.abs(position.x-lastReportedPos.x) +
  52.             math.abs(position.y-lastReportedPos.y) +
  53.             math.abs(position.z-lastReportedPos.z)
  54.     if d>8 then
  55.       reportPos("moved")
  56.     end
  57.   end    
  58. end        
  59.  
  60. local function loadHelp(filename)
  61.   if fs.exists(filename) then
  62.     local file=fs.open(filename,"r")
  63.     local text=file.readAll()
  64.     file.close()
  65.     return text
  66.   end
  67. end
  68.  
  69. local function loadAction()
  70.   local text=loadHelp(".action")
  71.   return text
  72. end
  73.  
  74. local function loadMonitor()
  75.   local text=loadHelp(".monitor")
  76.   if text then
  77.     monitorId=tonumber(text)
  78.   end
  79. end
  80.  
  81. function gpsUpdate()
  82.   local succ,x,y,z=pcall(gps.locate,1)
  83.   if succ and x then
  84.     position=vector.new(x,y,z)
  85.     if native.forward() then
  86.       local nx,ny,nz=gps.locate(1)
  87.       native.back()
  88.       if nx<x then
  89.         direction=3
  90.       elseif nx>x then
  91.         direction=1
  92.       elseif nz<z then
  93.         direction=0
  94.       else
  95.         direction=2
  96.       end
  97.     elseif native.back() then
  98.       local nx,ny,nz=gps.locate(1)
  99.       native.forward()
  100.       if nx<x then
  101.         direction=1
  102.       elseif nx>x then
  103.         direction=3
  104.       elseif nz<z then
  105.         direction=2
  106.       else
  107.         direction=0
  108.       end
  109.     else
  110.       native.turnLeft()
  111.       if native.forward() then
  112.         local nx,ny,nz=gps.locate(1)
  113.         native.back()        
  114.         if nx<x then
  115.           direction=0
  116.         elseif nx>x then
  117.           direction=2
  118.         elseif nz<z then
  119.           direction=1
  120.         else
  121.           direction=3
  122.         end
  123.       elseif native.back() then
  124.         local nx,ny,nz=gps.locate(1)
  125.         native.forward()        
  126.         if nx<x then
  127.           direction=2
  128.         elseif nx>x then
  129.           direction=0
  130.         elseif nz<z then
  131.           direction=3
  132.         else
  133.           direction=1
  134.         end
  135.       end
  136.       native.turnRight()
  137.     end
  138.   end
  139. end
  140.  
  141. local function loadPosition()  
  142.   local text=loadHelp(".position")
  143.   if text then
  144.     local x, y, z, d=string.match(text,"^(-?%d+)%s+(-?%d+)%s+(-?%d+)%s+(%d+)$")
  145.     position=vector.new(tonumber(x),tonumber(y),tonumber(z))
  146.     direction=tonumber(d)
  147.   end
  148. end
  149.  
  150. local function loadSelected()
  151.   local text=loadHelp(".selected")
  152.   if text then
  153.     selectedSlot=tonumber(text)
  154.     native.select(selectedSlot)
  155.   else
  156.     --make sure they agree at least
  157.     selectedSlot=1
  158.     native.select(1)
  159.   end
  160. end
  161.  
  162. local function loadPosStack()  
  163.   local text=loadHelp(".posStack")
  164.   if text then
  165.     posStack=textutils.unserialize(text)
  166.   else
  167.     posStack={}
  168.   end
  169. end
  170.  
  171. function loadState()
  172.   print("loadMonitor()")
  173.   loadMonitor()
  174.   print("loadPosition()")
  175.   loadPosition()
  176.   print("loadSelected()")
  177.   loadSelected()
  178.   ---[[
  179.   print("loadPosStack()")
  180.   loadPosStack()
  181.   --]]
  182.   print("loading inventory...")  
  183.   myInventory=inventory.load(".inventory")
  184.   if myInventory==nil then
  185.     myInventory=inventory.create(16,true)
  186.   else
  187.     myInventory.isMe=true
  188.   end
  189.   myInventory.autoSave=true
  190.  
  191. end
  192.  
  193. local function saveHelp(filename, text)
  194.   if text and text~="" then
  195.     file=fs.open(filename,"w")
  196.     file.write(text)
  197.     file.close()
  198.   else
  199.     fs.delete(filename)
  200.   end
  201. end
  202.  
  203. local function saveMonitor()
  204.   if monitorId then
  205.     saveHelp(".monitor",monitorId)
  206.   end
  207. end
  208.      
  209. local function savePosition()
  210.   saveHelp(".position",position.x.." "..position.y.." "..position.z.." "..direction)
  211.   reportPosIfChanged()  
  212. end
  213.  
  214. local function saveSelected()
  215.   saveHelp(".selectedSlot",selectedSlot)
  216. end
  217.  
  218. local function savePosStack()
  219.   saveHelp(".posStack",gutils.serialize(posStack))  
  220. end
  221.  
  222. function saveState()
  223.   savePosition()
  224.   saveSelected()
  225.   savePosStack()
  226.   inventory.save(myInventory,".inventory")
  227. end
  228.  
  229.  
  230. --[[===== public API functions ====]]--
  231.  
  232. function setMonitorId(id)
  233.   monitorId=id
  234.   saveMonitor()  
  235. end
  236.  
  237. function getMonitorId()
  238.   return monitorId
  239. end
  240.      
  241. --[[
  242. Convert the parameter into a turtlex
  243. direction value (0=north, 1=east,
  244. 2=south, 3=north). Accepts numbers,
  245. which are range-checked, or strings,
  246. which are matched to "north," "south,"
  247. "east," or "west," ignoring case and
  248. allowing for abitrary abbreviations
  249. (ex, "n", "No", "noR", or "NORTH" all
  250. match "north" and return as "0")
  251. returns nil on invalid values
  252. --]]
  253. function todirection(val)
  254.    if type(val) == "number" then
  255.      return val>=0 and val<=3 and val or nil
  256.    elseif type(val)=="string" then
  257.      for i,dir in pairs({"north","east","south","west"}) do
  258.        if #val<=#dir and string.sub(dir,1,#val) == string.lower(val) then
  259.          return i-1
  260.        end
  261.      end      
  262.    end
  263. end
  264.  
  265. --[[
  266. Converts a turtlex direction into a
  267. string, north/south/east/west, if
  268. parameter is invalid returns nil.
  269. --]]
  270. function directionToString(dir)
  271.   if dir==0 then return "north"
  272.   elseif dir==1 then return "east"
  273.   elseif dir==2 then return "south"
  274.   elseif dir==3 then return "west"
  275.   end
  276. end
  277.  
  278.  
  279. --[[
  280. compares actual turtle inventory to
  281. myInventory, updates all quantities, 0s
  282. type for newly-empty slots and attempts
  283. to identify any new items, attaching
  284. "unknown" tags to those that do not
  285. match available items.
  286.  
  287. return: changed, added, removed
  288. changed : boolean, true if anything
  289.   changed.
  290. added/removed: arrays of tables for each
  291.   slot which gained or lost items. Each
  292.   table has slot, type, and count, where
  293.   count is how many were added/removed.
  294. --]]
  295. function updateInventory()
  296.   --save selected slot to reselect when done
  297.   local changed=false
  298.   local prevSlot=selectedSlot
  299.   local addedStuff={}
  300.   local removedStuff={}
  301.   for i=1,16,1 do
  302.     local turtleCount=native.getItemCount(i)
  303.     local invCount=myInventory.slots[i].quantity
  304.     if invCount~=turtleCount then
  305.       --item count has changed...
  306.       changed=true
  307.       if invCount==0 then
  308.         --we had none before, have to compare to other types
  309.         select(i)
  310.         local found=false      
  311.         for j=1,16,1 do
  312.           if i~=j then
  313.             if myInventory.slots[j].type~=0 and compareTo(j) then
  314.               --got a match
  315.               myInventory.slots[i].type=myInventory.slots[j].type
  316.               found=true
  317.               break
  318.             end
  319.           end
  320.         end
  321.         if not found then
  322.           myInventory.slots[i].type=myInventory:getNextUnknownType()
  323.         end
  324.       elseif turtleCount==0 then
  325.         --add to dropped
  326.         removedStuff[#removedStuff+1]={
  327.           type=myInventory.slots[i].type,
  328.           count=myInventory.slots[i].quantity,
  329.           slot=i,
  330.         }
  331.         --we don't have anymore, zero type
  332.         myInventory.slots[i].type=0
  333.       end
  334.       --if we have more now...
  335.       if turtleCount>invCount then
  336.         --add to newstuff list
  337.         addedStuff[#addedStuff+1]= {
  338.           type=myInventory.slots[i].type,
  339.           count=turtleCount-invCount,
  340.           slot=i,
  341.         }
  342.       end
  343.       --in ALL cases, update quantity
  344.       myInventory.slots[i].quantity=native.getItemCount(i)
  345.     end
  346.   end
  347.   if changed then
  348.     inventory.save(myInventory,".inventory")
  349.   end
  350.   select(prevSlot)
  351.   return changed, addedStuff, removedStuff
  352. end
  353.  
  354. --[[
  355. internal, helper function for
  356. directional move functions  
  357. --]]
  358. local function movehelp(moveFunc, unmoveFunc, digFunc, detectFunc, attackFunc, dirv, count, onFail, onStepCallback)
  359.   count=count or 1
  360.   for i=1,count,1 do
  361.     local nextPosition=position+dirv
  362.     local moveRes=moveFunc()
  363.     if moveRes==false then
  364.       if not detectFunc() and hostileMode then
  365.         repeat
  366.           while attackFunc() do end
  367.         until moveFunc()
  368.        
  369.       else
  370.         if onFail=="return" then
  371.           local succ,dist
  372.           succ,dist=unmoveFunc(i-1,"stop")
  373.           return false, i-1-dist
  374.         elseif onFail=="dig" then
  375.           local res=false
  376.           local tries=0
  377.           repeat
  378.             --retry..
  379.             digFunc()
  380.             res=moveFunc()
  381.             tries=tries+1
  382.           until res==true or tries>=20
  383.           if res==false then
  384.             return false,i-1
  385.           end
  386.         else --default stop
  387.           return false, i-1
  388.         end
  389.       end
  390.     end
  391.     if onStepCallback then onStepCallback() end
  392.     position=nextPosition
  393.     savePosition()
  394.   end
  395.   return true, count
  396. end
  397.  
  398. function forward(count, onFail, onStepCallback)
  399.   local res1,res2=movehelp(native.forward,back,dig,native.detect,native.attack,dirVMap[direction], count, onFail, onStepCallback)
  400.   return res1,res2
  401. end
  402.  
  403. function back(count, onFail, onStepCallback)
  404.   local res1,res2=movehelp(native.back,forward,digBack,detectBack,attackBack,(dirVMap[(direction+2)%4]), count, onFail, onStepCallback)
  405.   return res1,res2
  406. end
  407.  
  408. function up(count, onFail, onStepCallback)
  409.   local res1,res2=movehelp(native.up,down,digUp,native.detectUp,native.attackUp,vector.new(0,1,0), count, onFail, onStepCallback)
  410.   return res1,res2
  411. end
  412.  
  413. function down(count, onFail, onStepCallback)
  414.   local res1,res2=movehelp(native.down,up,digDown,native.detectDown,native.attackBack,vector.new(0,-1,0), count, onFail, onStepCallback)
  415.   return res1,res2
  416. end
  417.  
  418. function left(count, onFail, onStepCallback)
  419.   turnLeft()
  420.   local res,c=forward(count,onFail, onStepCallback)
  421.   turnRight()
  422.   return res,c
  423. end
  424.  
  425. function right(count, onFail)
  426.   turnRight()
  427.   local res,c=forward(count,onFail, onStepCallback)
  428.   turnLeft()
  429.   return res,c
  430. end
  431.  
  432. function turnLeft()  
  433.   direction=(direction+3)%4
  434.   native.turnLeft()
  435.   savePosition()
  436.   return true
  437. end
  438.  
  439. function turnRight()
  440.   direction=(direction+1)%4
  441.   native.turnRight()
  442.   savePosition()
  443.   return true
  444. end
  445.  
  446. function turnAround()
  447.   direction=(direction+1)%4
  448.   native.turnLeft()
  449.   savePosition()
  450.   direction=(direction+1)%4
  451.   native.turnLeft()
  452.   savePosition()
  453.   return true
  454. end
  455.  
  456.  
  457. function getPosition()
  458.    return position.x,position.y,position.z
  459. end
  460.  
  461. --gets the chunk coordinates
  462. function getChunk()
  463.   return math.floor(position.x/16), math.floor(position.z/16)
  464. end
  465.  
  466. --gets position within chunk (range 0-15)
  467. function getChunkPosition()
  468.   return position.x%16, position.z%16
  469. end
  470.  
  471. function setPosition(x,y,z)
  472.   position=vector.new(x,y,z)
  473. end
  474.  
  475. function getDirection()
  476.   return direction
  477. end
  478.  
  479. function getDirectionV(dir)
  480.   if dir==nil or dir=="forward" then
  481.     return dirVMap[direction]
  482.   end
  483.   if dir=="back" then
  484.     return dirVMap[(direction+2)%4]
  485.   end
  486.   if dir=="left" then
  487.     return dirVMap[(direction+3)%4]
  488.   end
  489.   if dir=="right" then
  490.     return dirVMap[(direction+1)%4]
  491.   end
  492.   if dir=="up" then
  493.     return vector.new( 0, 1,0)
  494.   end
  495.   if dir=="down" then
  496.     return vector.new( 0, -1,0)    
  497.   end
  498.   return nil --invalid direction
  499. end
  500.  
  501. function setDirection(dir)
  502.   local newdir=todirection(dir)
  503.   if newdir then
  504.     direction=newdir
  505.   end
  506. end
  507.  
  508. function move(x, y, z, onBlocked)
  509.   local succ, dist, blocked, done
  510.   local prevDir=direction
  511.   local moves={}
  512.   local dig=false
  513.   while true do
  514.     blocked=true
  515.     done=true
  516.     if x>0 then
  517.       face("east")
  518.       succ,dist=forward(x,"stop")
  519.       x=x-dist
  520.       if dist>0 then
  521.         moves[#moves+1]={dir="east",dist=dist}
  522.         blocked=false
  523.       end        
  524.       done=done and succ
  525.     elseif x<0 then
  526.       face("west")
  527.       succ,dist=forward(-x,"stop")
  528.       x=x+dist
  529.       if dist>0 then
  530.         moves[#moves+1]={dir="west",dist=dist}        
  531.         blocked=false
  532.       end
  533.       done=done and succ
  534.     end
  535.     if y>0 then
  536.       succ,dist=up(y,"stop")
  537.       y=y-dist
  538.       if dist>0 then
  539.         moves[#moves+1]={dir="up",dist=dist}
  540.         blocked=false
  541.       end
  542.       done=done and succ
  543.     elseif y<0 then
  544.       succ,dist=down(-y,"stop")
  545.       y=y+dist
  546.       if dist>0 then
  547.         moves[#moves+1]={dir="down",dist=dist}
  548.         blocked=false
  549.       end
  550.       done=done and succ
  551.     end
  552.     if z>0 then
  553.       face("south")
  554.       succ,dist=forward(z,"stop")
  555.       z=z-dist
  556.       if dist>0 then
  557.         moves[#moves+1]={dir="south",dist=dist}
  558.         blocked=false
  559.       end
  560.       done=done and succ
  561.     elseif z<0 then
  562.       face("north")
  563.       succ,dist=forward(-z,"stop")
  564.       z=z+dist
  565.       if dist>0 then
  566.         moves[#moves+1]={dir="north",dist=dist}
  567.         blocked=false
  568.       end
  569.       done=done and succ
  570.     end
  571.     if done then
  572.       return true, moves
  573.     end
  574.     if blocked then
  575.       if onBlocked=="return" then
  576.         for i=#moves,1,-1 do
  577.           if moves[i].dir=="north" then
  578.             face("south")
  579.             forward(moves[i].dist)
  580.           elseif moves[i].dir=="south" then
  581.             face("north")
  582.             forward(moves[i].dist)
  583.           elseif moves[i].dir=="east" then
  584.             face("west")
  585.             forward(moves[i].dist)
  586.           elseif moves[i].dir=="west" then
  587.             face("east")
  588.             forward(moves[i].dist)
  589.           elseif moves[i].dir=="up" then
  590.             down(moves[i].dist)
  591.           elseif moves[i].dir=="down" then
  592.             up(moves[i].dist)
  593.           end
  594.         end
  595.         face(prevDir)
  596.         return false
  597.       elseif onBlocked=="dig" then
  598.         succ=true
  599.         if x>0 then
  600.           face("east")
  601.           succ=forward(x,"dig") and succ
  602.           moves[#moves+1]={dir="east",dist=x}
  603.         elseif x<0 then          
  604.           face("west")
  605.           succ=forward(-x,"dig") and succ
  606.           moves[#moves+1]={dir="west",dist=-x}
  607.         end
  608.         if z>0 then
  609.           face("south")
  610.           succ=forward(z,"dig") and succ
  611.           moves[#moves+1]={dir="south",dist=z}
  612.         elseif z<0 then
  613.           face("north")
  614.           succ=forward(-z,"dig") and succ
  615.           moves[#moves+1]={dir="north",dist=-z}
  616.         end
  617.         if y>0 then
  618.           succ=up(y,"dig") and succ
  619.           moves[#moves+1]={dir="up",dist=y}
  620.         elseif y<0 then
  621.           succ=down(-y,"dig") and succ
  622.           moves[#moves+1]={dir="down",dist=-y}
  623.         end
  624.         return succ, moves
  625.       else
  626.         return false
  627.       end
  628.     end
  629.   end
  630. end
  631.  
  632. function goto(x,y,z,onBlocked)
  633.   return move(x-position.x,y-position.y,z-position.z,onBlocked)
  634. end
  635.  
  636. function face(newDirection)
  637.   newDirection=todirection(newDirection)
  638.   if newDirection==nil then
  639.     return nil
  640.   end
  641.   turns=newDirection-direction
  642.   if turns>2 then turns=turns-4 end
  643.   if turns<-2 then turns=turns+4 end
  644.   if turns==-1 then
  645.     turnLeft()    
  646.   elseif turns==1 then
  647.     turnRight()
  648.   elseif turns~=0 then
  649.     turnAround()
  650.   end
  651.   return true
  652. end
  653.  
  654.  
  655. function pushPos()
  656.   posStack[#posStack+1]={position,direction}
  657.   savePosStack()
  658. end
  659.  
  660. function popPos()
  661.   if #posStack>0 then
  662.     local t=posStack[#posStack]
  663.     local pos=t[1]
  664.     local dir=t[2]
  665.     posStack[#posStack]=nil
  666.     savePosStack()
  667.     --if go then
  668.       local res=goto(pos.x,pos.y,pos.z)
  669.       face(dir)
  670.       return res
  671.     --else
  672.     --  return true
  673.     --end
  674.   end
  675.   return nil
  676. end
  677.  
  678. function topPos()
  679.   return posStack[#posStack]
  680. end
  681.  
  682. function getPosStackSize()
  683.   return #posStack
  684. end
  685.  
  686. function getPosStackItem(index)
  687.   if type(index)~="number" then
  688.     error("turtlex:getPosStackItem: parameter must be a number!")
  689.   end
  690.   if index<=0 or index>#posStack then
  691.     error("turtlex:getPosStackItem: index out of range!")
  692.   end
  693.   return posStack[index]
  694. end
  695.  
  696. function clearStack()
  697.   posStack={}
  698.   savePosStack()
  699. end
  700.  
  701.  
  702. function select(index)
  703.   succ,err = pcall(native.select,index)
  704.   if succ then
  705.     selectedSlot=index
  706.     saveSelected()
  707.     return succ
  708.   else
  709.     return false, err
  710.   end
  711. end
  712.  
  713. function getSelected()
  714.   return selectedSlot, myInventory.slots[selectedSlot].type
  715. end
  716.  
  717. function getInventory()
  718.   return myInventory
  719. end
  720.  
  721. function getItemType(slot)
  722.   local prevSlot=selectedSlot
  723.   if slot~=nil then
  724.     select(slot)
  725.   else
  726.     slot=selectedSlot
  727.   end
  728.   local res=myInventory.slots[selectedSlot].type
  729.   if slot~=prevSlot then
  730.     select(prevSlot)
  731.   end
  732.   return res
  733. end
  734.  
  735. function setItemType(type, slot)
  736.   if slot==nil then
  737.     slot=selectedSlot
  738.   end
  739.   myInventory:setType(slot,type)
  740. end
  741.  
  742.  
  743. function getItemCount(ident)
  744.   if ident==nil then
  745.     ident=selectedSlot
  746.   elseif type(ident)~="number" then
  747.     if tonumber(ident) then
  748.       ident=tonumber(ident)
  749.     else
  750.       --slot is not a number, must be a type!
  751.       local total=0
  752.       for slot in typeSlots(ident) do
  753.         total=total+native.getItemCount(slot)
  754.       end
  755.       return total      
  756.     end
  757.   end
  758.   --if it gets here, it was a slot#
  759.   return native.getItemCount(ident)
  760. end
  761.  
  762. function getItemSpace(slot)
  763.   if slot==nil then slot=selectedSlot end
  764.   return native.getItemSpace(slot)
  765. end
  766.  
  767. function findItemType(type, after)
  768.   return myInventory:findSlot(type,after)
  769. end
  770.  
  771. function transferTo(slot,qty)
  772.   local res=native.transferTo(slot,qty)
  773.   if res then
  774.     updateInventory()
  775.   end
  776.   return res
  777. end
  778.  
  779. local function iterTypeSlots(type,after)
  780.   local v=findItemType(type,after)
  781.   if v~=0 then
  782.     return v
  783.   end
  784. end
  785.  
  786. function typeSlots(t)
  787.   return iterTypeSlots, t, 0
  788. end
  789.  
  790. function findLastItemType(type, before)
  791.   for i=before-1,1,-1 do
  792.     if myInventory.slots[i].type==type then
  793.       return i
  794.     end
  795.   end
  796.   return 0
  797. end
  798.  
  799. local function iterTypeSlotsRev(type,before)
  800.   local v=findLastItemType(type,before)
  801.   if v~=0 then
  802.     return v
  803.   end
  804. end
  805.  
  806.  
  807. function typeSlotsRev(t)
  808.   return iterTypeSlotsRev, t, 17
  809. end
  810.  
  811. function displayInv()
  812.   myInventory:display()
  813. end
  814.  
  815.  
  816. local function digHelp(slot,digFunc)
  817.   local prev=selectedSlot
  818.   local items={}
  819.   if slot~=nil then
  820.     select(slot)
  821.   else
  822.     slot=prev
  823.   end
  824.  
  825.   local res=digFunc()
  826.   if res then
  827.     --successfully dug, attempt to identify
  828.     local suc,add,sub=updateInventory()
  829.     if suc then
  830.       items=add
  831.     end
  832.   end
  833.  
  834.   --reselect previous slot
  835.   if slot~=prev then
  836.     select(prev)
  837.   end
  838.  
  839.   return res, items
  840. end
  841.  
  842. function dig(slot)
  843.   return digHelp(slot,native.dig)
  844. end
  845.  
  846. function digUp(slot)
  847.   return digHelp(slot,native.digUp)  
  848. end
  849.  
  850. function digDown(slot)
  851.   return digHelp(slot,native.digDown)
  852. end
  853.  
  854. function digBack(slot)
  855.   turnAround()
  856.   res=dig(slot)
  857.   turnAround()
  858.   return res
  859. end
  860.  
  861. function digLeft(slot)
  862.   turnLeft()
  863.   res=dig(slot)
  864.   turnRight()
  865.   return res
  866. end
  867.  
  868. function digRight(slot)
  869.   turnRight()
  870.   res=dig(slot)
  871.   turnLeft()
  872.   return res
  873. end
  874.  
  875.  
  876. local function indexHelper(index)
  877.   local slot=selectedSlot
  878.   if index~=nil then
  879.     if type(index)=="string" then
  880.       slot=findItemType(index)
  881.       if slot==0 then
  882.         return nil,"turtlex:compare: no reference sample for type '"..index.."' in inventory!"
  883.       end
  884.     elseif type(index)=="number" then
  885.       slot=index
  886.     else
  887.       return nil, "turtlex:compare: invalid parameter, expected number or string, got "..type(index)
  888.     end
  889.   end
  890.   return slot
  891. end
  892.  
  893. local function placeHelp(index,placeFunc, extra)
  894.   local placeParam=extra
  895.   local slot,err=indexHelper(index)  
  896.   if not slot then
  897.     placeParam=index
  898.     slot,err=indexHelper(extra)
  899.     if not slot then
  900.       return nil, err
  901.     end
  902.   end
  903.  
  904.   local prev=selectedSlot
  905.   if slot~=prev then
  906.     select(slot)
  907.   end
  908.  
  909.   res=placeFunc(placeParam)
  910.   if res then
  911.     --successfully placed
  912.     updateInventory()
  913.   end
  914.  
  915.   --restore selected slot
  916.   if slot~=prev then
  917.     select(prev)
  918.   end
  919.   return res
  920.  
  921. end
  922.  
  923. function place(index,extra)
  924.   return placeHelp(index,native.place,extra)
  925. end
  926.  
  927. function placeUp(index,extra)
  928.   return placeHelp(index,native.placeUp)
  929. end
  930.  
  931. function placeDown(index,extra)
  932.   return placeHelp(index,native.placeDown,extra)
  933. end
  934.  
  935. function placeBack(slot,extra)
  936.   turnAround()
  937.   res=place(slot,native.place,extra)
  938.   turnAround()
  939.   return res
  940. end
  941.  
  942. function placeLeft(slot,extra)
  943.   turnLeft()
  944.   res=place(slot,native.place,extra)
  945.   turnRight()
  946.   return res
  947. end
  948.  
  949. function placeRight(slot,extra)
  950.   turnRight()
  951.   res=place(slot,native.place,extra)
  952.   turnLeft()
  953.   return res
  954. end
  955.  
  956.  
  957.  
  958. local function compareHelp(index,compareFunc)
  959.   local prevSlot=selectedSlot
  960.   local slot, err=indexHelper(index)
  961.   if slot==nil then
  962.     return slot, err
  963.   end
  964.   if prevSlot~=slot then
  965.     select(slot)  
  966.   end
  967.   local res=compareFunc()
  968.   if slot~=prevSlot then
  969.     select(prevSlot)
  970.   end
  971.   return res
  972. end
  973.  
  974. function compare(index)
  975.   return compareHelp(index,native.compare)
  976. end
  977.  
  978. function compareUp(index)
  979.   return compareHelp(index,native.compareUp)
  980. end
  981.  
  982. function compareDown(index)
  983.   return compareHelp(index,native.compareDown)
  984. end
  985.  
  986. function compareLeft(index)
  987.   turtle.turnLeft()
  988.   local res,err=compare(index)
  989.   turtle.turnRight()
  990.   return res, err
  991. end
  992.  
  993. function compareRight(index)
  994.   turtle.turnRight()
  995.   local res,err=compare(index)
  996.   turtle.turnLeft()
  997.   return res
  998. end
  999.  
  1000. function compareBack(index)
  1001.   turtle.turnAround()
  1002.   local res,err=compare(index)
  1003.   turtle.turnAround()
  1004.   return res, err
  1005. end
  1006.  
  1007. function compareAll(index)
  1008.   local prevSlot=selectedSlot
  1009.   local slot, err=indexHelper(index)
  1010.   if slot==nil then
  1011.     return slot, err
  1012.   end
  1013.   if prevSlot~=slot then
  1014.     select(slot)  
  1015.   end
  1016.   dirs={"forward","right","back","left"}
  1017.   matches={}
  1018.   if native.compareUp() then
  1019.     matches[#matches+1]="up"
  1020.   end
  1021.   if native.compareDown() then
  1022.     matches[#matches+1]="down"
  1023.   end
  1024.   for i=1,4,1 do  
  1025.     if native.compare() then
  1026.       matches[#matches+1]=dirs[i]
  1027.     end
  1028.     turtle.turnRight()
  1029.   end
  1030.    
  1031.   if prevSlot~=slot then
  1032.     select(prevSlot)
  1033.   end
  1034.   return #matches, matches
  1035. end
  1036.  
  1037.  
  1038. function compareTo(slotNum, index)
  1039.   local prevSlot=selectedSlot
  1040.   local slot,err=indexHelper(index)
  1041.  
  1042.   if slot==nil then
  1043.     return slot,err
  1044.   end
  1045.  
  1046.   if prevSlot~=slot then
  1047.     select(slot)  
  1048.   end
  1049.   res=native.compareTo(slotNum)
  1050.   if prevSlot~=slot then
  1051.     select(prevSlot)
  1052.   end  
  1053.  
  1054.   return res
  1055. end
  1056.  
  1057.  
  1058. detect=native.detect
  1059. detectUp=detectUp
  1060. detectDown=detectDown
  1061.  
  1062. function detectLeft()
  1063.   turnLeft()
  1064.   local res=detect()
  1065.   turnRight()
  1066.   return res
  1067. end
  1068.  
  1069.  
  1070. function detectRight()
  1071.   turnRight()
  1072.   local res=detect()
  1073.   turnLeft()
  1074.   return res
  1075. end
  1076.  
  1077. function detectBack()
  1078.   turnAround()
  1079.   local res=detect()
  1080.   turnAround()
  1081.   return res
  1082. end
  1083.  
  1084.  
  1085. local function dropHelp(quantity, index, dropFunc)
  1086.   quantity=quantity or 64
  1087.   if quantity==0 then
  1088.     return true
  1089.   end
  1090.   local prevSlot=selectedSlot
  1091.   local slot,err=indexHelper(index)  
  1092.   if slot==nil then
  1093.     return false, err
  1094.   end
  1095.   if slot~=prevSlot then
  1096.     select(slot)
  1097.   end
  1098.   local prevCount=turtlex.getItemCount(index)
  1099.   local res=false
  1100.   if quantity<0 then
  1101.     quantity=prevCount+quantity
  1102.   end
  1103.   if not index or type(index)=="number" then
  1104.     res=dropFunc(quantity)
  1105.   else
  1106.     local dropped=0
  1107.     for slot in typeSlotsRev(index) do
  1108.       res=true
  1109.       turtlex.select(slot)
  1110.       if native.getItemCount(slot)+dropped<quantity then
  1111.         dropped=dropped+native.getItemCount(slot)
  1112.         dropFunc(math.min(quantity,64))  
  1113.       else
  1114.         dropFunc(quantity-dropped)
  1115.         break
  1116.       end
  1117.     end
  1118.   end
  1119.   if res then
  1120.     updateInventory()
  1121.   end
  1122.   if selectedSlot~=prevSlot then
  1123.     select(prevSlot)
  1124.   end
  1125.  
  1126.   return res, quantity>=prevCount and prevCount or quantity
  1127. end
  1128.  
  1129. function drop(quantity, index)
  1130.   return dropHelp(quantity,index,native.drop)
  1131. end
  1132.  
  1133. function dropUp(quantity, index)
  1134.   return dropHelp(quantity,index,native.dropUp)
  1135. end
  1136.  
  1137. function dropDown(quantity, index)
  1138.   return dropHelp(quantity,index,native.dropDown)
  1139. end
  1140.  
  1141. function dropLeft(quantity,index)
  1142.   turnLeft()
  1143.   local res=dropHelp(quantity,index,native.drop)
  1144.   turnRight()
  1145.   return res
  1146. end
  1147.  
  1148. function dropRight(quantity,index)
  1149.   turnRight()
  1150.   local res=dropHelp(quantity,index,native.drop)
  1151.   turnLeft()
  1152.   return res
  1153. end
  1154.  
  1155. function dropBack(quantity,index)
  1156.   turnAround()
  1157.   local res=dropHelp(quantity,index,native.drop)
  1158.   turnAround()
  1159.   return res
  1160. end
  1161.  
  1162.  
  1163. local function suckHelp(slot,suckFunc)
  1164.   local prevSlot=selectedSlot
  1165.   if slot==nil then
  1166.     slot=selectedSlot
  1167.   end
  1168.   if slot~=prevSlot then
  1169.     select(slot)
  1170.   end
  1171.   local res=suckFunc()
  1172.  
  1173.   local succ, add={}, rem;
  1174.   if res then
  1175.     succ,add,rem=updateInventory()
  1176.   end
  1177.  
  1178.   if slot~=prevSlot then
  1179.     select(prevSlot)
  1180.   end
  1181.   return res, add
  1182. end
  1183.  
  1184. function suck(slot)
  1185.   return suckHelp(slot,native.suck)
  1186. end
  1187.  
  1188. function suckUp(slot)
  1189.   return suckHelp(slot,native.suckUp)
  1190. end
  1191.  
  1192. function suckDown(slot)
  1193.   return suckHelp(slot,native.suckDown)
  1194. end
  1195.  
  1196. function suckLeft(slot)
  1197.   turnLeft()
  1198.   local res, qty=suckHelp(slot,native.suck)
  1199.   turnRight()
  1200.   return res,qty
  1201. end
  1202.  
  1203. function suckRight(slot)
  1204.   turnRight()
  1205.   local res, qty=suckHelp(slot,native.suck)
  1206.   turnLeft()
  1207.   return res,qty
  1208. end
  1209.  
  1210. function suckBack(slot)
  1211.   turnAround()
  1212.   local res, qty=suckHelp(slot,native.suck)
  1213.   turnAround()
  1214.   return res,qty
  1215. end
  1216.  
  1217.  
  1218. getFuelLevel=native.getFuelLevel
  1219.  
  1220.  
  1221. function refuel(quantity, index)
  1222.   quantity=quantity or 64
  1223.   local prevSlot=selectedSlot
  1224.   local res
  1225.   if type(index)=="string" then    
  1226.     for slot in typeSlotsRev(index) do
  1227.       if quantity<turtlex.getItemCount(slot) then
  1228.         select(slot)
  1229.         native.refuel(quantity)
  1230.         break
  1231.       else
  1232.         quantity=quantity-turtlex.getItemCount(slot)
  1233.         select(slot)
  1234.         native.refuel()
  1235.       end
  1236.     end
  1237.   else
  1238.     local slot,err=indexHelper(index)
  1239.     if slot==nil then
  1240.       return false, err
  1241.     end
  1242.     if prevSlot~=slot then
  1243.       select(slot)
  1244.     end
  1245.       res=native.refuel(quantity)
  1246.     if res==true then
  1247.       updateInventory()
  1248.     end
  1249.   end
  1250.   select(prevSlot)
  1251.   return res
  1252. end
  1253.  
  1254. function craft(quantity, slot, outputType)
  1255.   if turtle.craft==nil then
  1256.     return false, "turtlex:craft: Only crafting turtles can craft!"
  1257.   end
  1258.  
  1259.   local res
  1260.   prevSlot=selectedSlot
  1261.   if slot==nil then
  1262.     slot=selectedSlot
  1263.   elseif slot~=prevSlot then
  1264.     select(slot)
  1265.   end
  1266.   if quantity==nil then
  1267.     res=native.craft()
  1268.   else
  1269.     res=native.craft(quantity)
  1270.   end
  1271.   if slot~=prevSlot then
  1272.     select(prevSlot)
  1273.   end  
  1274.   if res==true then
  1275.     local wasChange, addedStuff, removedStuff = updateInventory()
  1276.     if wasChange==false then
  1277.       return res, "inconsistent results from updateInventory - craft reports success, but no change or no added items reported?"
  1278.     end
  1279.     --did they give us an expected output type?
  1280.     if outputType~=nil and outputType~="" and outputType~=0 and outputType~="unknown" then
  1281.       local addedType
  1282.       if #addedStuff>0 then
  1283.         addedType=addedStuff[1].type
  1284.       else
  1285.         addedType=myInventory.getItemType(slot)
  1286.       end
  1287.       for i=2,#addedStuff,1 do
  1288.         if addedStuff[i].type~=addedType then
  1289.           return res, "inconsistent results from updateInventory - multiple new item types detected!"
  1290.         end
  1291.       end
  1292.       setItemType(outputType,addedStuff[1].slot)
  1293.     end
  1294.   end
  1295.   return res
  1296. end
  1297.  
  1298.  
  1299. function attackHelp(attackFunc,untilFalse)
  1300.   local res=attackFunc()
  1301.   while res and untilFalse do
  1302.     sleep(.4)
  1303.     res=attackFunc()
  1304.   end
  1305.   local add
  1306.   if res then
  1307.     _,add,_=updateInventory()
  1308.   end
  1309.   return res,add
  1310. end
  1311.  
  1312. function attack(untilFalse)
  1313.   return attackHelp(native.attack,untilFalse)
  1314. end
  1315.  
  1316. function attackUp(untilFalse)
  1317.   return attackHelp(native.attackUp,untilFalse)
  1318. end
  1319.  
  1320. function attackDown(untilFalse)
  1321.   return attackHelp(native.attackDown,untilFalse)
  1322. end
  1323.  
  1324. function attackLeft(untilFalse)
  1325.   turtlex.turnLeft()
  1326.   res={attackHelp(native.attack,untilFalse)}
  1327.   turtlex.turnRight()
  1328.   return unpack(res)
  1329. end
  1330.  
  1331. function attackRight(untilFalse)
  1332.   turtlex.turnRight()
  1333.   res={attackHelp(native.attack,untilFalse)}
  1334.   turtlex.turnLeft()
  1335.   return unpack(res)
  1336. end
  1337.  
  1338. function attackBack(untilFalse)
  1339.   turtlex.turnAround()
  1340.   res={attackHelp(native.attack,untilFalse)}
  1341.   turtlex.turnAround()
  1342.   return unpack(res)
  1343. end
  1344.  
  1345. function isHostile()
  1346.   return hostileMode
  1347. end
  1348.  
  1349. function setHostile(state)
  1350.   hostileMode=state==true
  1351. end
  1352.  
  1353. --[[=== api initialization code ===]]--
  1354. print("loadState()")
  1355. sleep(1+math.random(1,1000)/1000)
  1356. loadState()
  1357. --try to update position from gps, if I even have a modem
  1358. if peripheral.getType("right")=="modem" then
  1359.   print("updating position via GPS...")
  1360.   rednet.open("right")
  1361.   gpsUpdate()
  1362. end
Advertisement
Add Comment
Please, Sign In to add comment