Advertisement
Wojbie

turtle-ext v0.4

Mar 3rd, 2015
530
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 35.79 KB | None | 0 0
  1. --# Turtle Extended API v0.4
  2. --# Made By Wojbie
  3. --# http://pastebin.com/X8NEcEVy
  4.  
  5.  
  6. --Rebuild and restructure!
  7. --split internal and front functions
  8. --Separate functions into subtables.
  9. --API Settings -  TagControl,DaemonControl
  10. --Utility ? --making a point ect?
  11.  
  12. --work on naming convention
  13. --cram similiar function into one with some flags.
  14. --add some kind of map system. - auto save contents of inspection. (Deamon idea? Scan all turtle sees ever so often?)
  15. --add onScan function()
  16.  
  17. --defininf variables for whole api
  18.  
  19. --investigame turtle.inventory event for daemon
  20.  
  21. --crafting database? use tags for types of wood ect.
  22.  
  23.  
  24.  
  25.  
  26.  
  27. --##     ERROR TESTS     ##--
  28.  
  29. if shell or multishell then
  30.     print("You have run this api instead of loading it. There is no point in doing that. Use os.loadApi to load it.")
  31.     return
  32. end
  33.  
  34. if not turtle then
  35.     error("This is not a turtle. This api will not work outside of the turtle.")
  36. end
  37.  
  38. --##     CONSTANTS     ##--
  39.  
  40. local oldturtle = turtle --Pointing local at global turtle (in case user overwrites it with this api)
  41. nativeTurtle=oldturtle --acces to basic turtle (in case user overwrites it with this api)
  42. versionName="TurtleExtended By Wojbie"
  43. versionNumber=0.4
  44.  
  45. --##     GLOBALS     ##--
  46.  
  47. local bMovelock = true --Is true if position of turtle is not set. Stops all movement functions. They will return false.
  48. local bScanner = false --Automatic scanning to map on movement? Slows movement down.
  49. local bBrutal = false --Automatic attacking if movement falls
  50. local bVacuum = false --Automatic vacuum as it moves around
  51. local pos
  52.  
  53. local bInMove = false
  54.  
  55.  
  56.  
  57. --##     SUBTABLES     ##--
  58.  
  59. util = {}
  60. tags = {}
  61. map = {}
  62.  
  63.  
  64. --##     RANDOM USEFULL FUCTIONS     ##--
  65.  
  66. local function save(A,B) local file = fs.open(tostring(A),"w") file.write(B) file.close() end
  67. local function saveT(A,B) save(A,textutils.serialize(B)) end
  68. local function saveTL(A,B) save(A,string.gsub(textutils.serialize(B),"\n%s*","")) end
  69.  
  70. local function get(A) local file = fs.open(tostring(A),"r") if not file then return false end local data = file.readAll() file.close() if data then return data end end
  71. local function getT(A) local data = get(A) if data then data = textutils.unserialize(data) end if data then return data end end
  72. local function getHttp(A) if not http.checkURL(A) then return false end local file = http.get(A) if not file then return false end local data = file.readAll() file.close() if data then return data end end
  73.  
  74. local function copyT(...) --Copy table - if more than one merge them - in case of overwriting values last one gets its way
  75. tArgs={...}
  76. local B={}
  77.     for _,A in pairs(tArgs) do
  78.         if A and type(A)=="table" then
  79.             for i,k in pairs(A) do
  80.                 if type(k)=="table" then B[i]=copyT( B[i] or {},k)
  81.                 else B[i]=k end
  82.             end
  83.         end
  84.     end
  85. return B
  86. end
  87.  
  88.  
  89. --##     TAG DATABASE     ##--
  90.    
  91. local ProtectedTags={["#All"]=true}
  92.  
  93. local tagList={ --#Modname tag is always added by dynamic code
  94. ["#bedrock"]={{"minecraft:bedrock"},{"factorization:FracturedBedrock"},},
  95. ["#stone"]={{"minecraft:stone"},},
  96. ["#cobble"]={{"minecraft:cobblestone"},},
  97. ["#dirt"]={{"minecraft:dirt",0},{"minecraft:grass"}},
  98. ["#podzol"]={{"minecraft:dirt",2}},
  99.  
  100. ["#sand"]={{"minecraft:sand"},},
  101. ["#gravel"]={{"minecraft:gravel"},},
  102.  
  103. ["#log"]={{"minecraft:log"},{"minecraft:log2"}},
  104. ["#leaves"]={{"minecraft:leaves"},{"minecraft:leaves2"}},
  105. ["#tree"]={"#log","#leaves"},
  106. ["#sapling"]={{"minecraft:sapling"}},
  107.  
  108. ["#gravity"]={"#sand","#gravel"},
  109.  
  110. ["#liquid"]={{"minecraft:flowing_lava"},{"minecraft:lava"},{"minecraft:flowing_water"},{"minecraft:water"}},
  111. ["#liquidSourceBlock"]={{"minecraft:flowing_lava",0},{"minecraft:lava",0},{"minecraft:flowing_water",0},{"minecraft:water",0}}, --Thanks to Bomb Bloke for helping me test that!
  112.  
  113. ["#containder"]={{"minecraft:chest"},},
  114.  
  115. ["#unique"]={{"minecraft:dragon_egg"}},
  116.  
  117. ["#ground"]={"#dirt","#stone"},
  118.  
  119. ["#ore"]={"#vanillaOre"},
  120. ["#mineableOre"]={"#vanillaOre"},
  121. ["#vanillaOre"]={{"minecraft:gold_ore"},{"minecraft:iron_ore"},{"minecraft:coal_ore"},{"minecraft:lapis_ore"},{"minecraft:diamond_ore"},{"minecraft:redstone_ore"},{"minecraft:emerald_ore"},{"minecraft:quartz_ore"}},
  122.  
  123. --["#sample"]={{"minecraft:stone"},{"minecraft:lava",1},"#stone"},
  124.  
  125.  
  126. --Blacklist tags
  127. ["#DigBlacklist"]={"#Blacklist",{"minecraft:mob_spawner"},"#ComputerCraft:","#computercraft:"}, --Spawners are to preacius to mine, Also no canibalism.
  128. ["#DigWhitelist"]={"#Whitelist",},
  129. ["#PlaceBlacklist"]={"#Blacklist",{"minecraft:bedrock"}}, --No placing Bedrock on my watch
  130. ["#PlaceWhitelist"]={"#Whitelist",},
  131. ["#Blacklist"]={},
  132. ["#Whitelist"]={},
  133.  
  134. --Test tags
  135. ["#TestAll"]={"#All"},
  136. ["#TestComputertag"]={"#ComputerCraft:","#computercraft:"},
  137. }
  138.  
  139. local lookupName={}
  140.  
  141. --[[{
  142. ["minecraft:stone"]=
  143.     {
  144.     [true]={["#stone"]=true},
  145.     [3]={["#stone3"]=true},
  146.     [m3]={["#stonem3"]=true},
  147.     [d3]={["#stoned3"]=true},
  148.     }
  149. }]]--
  150.  
  151. local lookupTag={}
  152.  
  153. --[[{
  154. ["#stone"]=
  155.     {
  156.     ["ground"]=true,
  157.     }
  158. }]]--
  159.  
  160. --Database operations
  161.  
  162. local function assigntag(tag,list)
  163.     for _,v in pairs(list) do  
  164.         if type(v)=="table" then --name meta or just name combo
  165.             if not v[2] then v[2] = true end
  166.             if not lookupName[v[1]] then lookupName[v[1]]={} end
  167.             if not lookupName[v[1]][v[2]] then lookupName[v[1]][v[2]]={} end
  168.             lookupName[v[1]][v[2]][tag]=true
  169.         elseif type(v)=="string" then --tag
  170.             if not lookupTag[v] then lookupTag[v]={} end
  171.             lookupTag[v][tag]=true
  172.         end
  173.     end
  174. end
  175.  
  176. local function removetag(tag,list)
  177.     for _,v in pairs(list) do  
  178.         if type(v)=="table" then --name meta or just name combo
  179.             if not v[2] then v[2] = true end
  180.             if not lookupName[v[1]] then lookupName[v[1]]={} end
  181.             if not lookupName[v[1]][v[2]] then lookupName[v[1]][v[2]]={} end
  182.             lookupName[v[1]][v[2]][tag]=nil
  183.         elseif type(v)=="string" then --tag
  184.             if not lookupTag[v] then lookupTag[v]={} end
  185.             lookupTag[v][tag]=nil
  186.         end
  187.     end
  188. end
  189.  
  190. --Filling the database
  191.  
  192. for i,k in pairs(tagList) do
  193.     assigntag(i,k)
  194. end
  195.  
  196. --User Accesable functions
  197.  
  198. tags.createTag = function(Tag) --Creates new tag
  199.     if tagList[Tag] then return false,"Tag Exists" end
  200.     if ProtectedTags[Tag] then return false,"Tag Protected" end
  201.     tagList[Tag]={}
  202.     return true
  203. end
  204. local createTag = tags.createTag
  205.  
  206. tags.deleteTag = function(Tag) --Deletes tag and all stuff regeristered to it.
  207.     if not tagList[Tag] then return false,"No such Tag" end
  208.     if ProtectedTags[Tag] then return false,"Tag Protected" end
  209.     removetag(Tag,tagList[Tag])
  210.     tagList[Tag]=nil
  211.     return true
  212. end
  213.  
  214. tags.isTag = function(Tag) --cheacks is tag exists
  215.     return tagList[Tag] and true or false
  216. end
  217. local isTag = tags.isTag
  218.  
  219. tags.addBlockToTag = function(Tag,Block,Meta)
  220.     if not tagList[Tag] then return false,"No such Tag" end
  221.     if ProtectedTags[Tag] then return false,"Tag Protected" end
  222.     if lookupName[Block] and lookupName[Block][Meta or true] and lookupName[Block][Meta or true][Tag] then return true end
  223.     if not tagList[Tag] then tagList[Tag] = {} end
  224.     table.insert(tagList[Tag],{Block,Meta or true})
  225.     assigntag(Tag,tagList[Tag]) --update lookup tables
  226.     return true
  227. end
  228.  
  229. tags.addSubTagToTag = function(Tag,Child)
  230.     if not tagList[Tag] then return false,"No such Tag" end
  231.     if ProtectedTags[Tag] then return false,"Tag Protected" end
  232.     if not tagList[Tag] then tagList[Tag] = {} end
  233.     if lookupTag[Child] and lookupTag[Child][Tag] then  return true end
  234.     table.insert(tagList[Tag],Child)
  235.     assigntag(Tag,tagList[Tag]) --update lookup tables
  236.     return true
  237. end
  238.  
  239. tags.listTag = function(Tag)
  240.     if not tagList[Tag] then return false,"No such Tag" end
  241.     if ProtectedTags[Tag] then return false,"Tag Protected" end
  242.     return copyT(tagList[Tag])
  243. end
  244.  
  245. tags.removeItemFromTag = function(Tag,num)
  246.     if not tagList[Tag] then return false,"No such Tag" end
  247.     if ProtectedTags[Tag] then return false,"Tag Protected" end
  248.     removetag(Tag,tagList[Tag])
  249.     table.remove(tagList[Tag],num)
  250.     assigntag(Tag,tagList[Tag])
  251.     return true
  252. end
  253.  
  254. tags.saveTags = function(A)
  255.     saveT(A or "/tag.log",tagList)
  256. end
  257.  
  258. tags.loadTags = function(A)
  259.     tagList=getT(A or"/tag.log") or {}
  260.     lookupName={}
  261.     lookupTag={}
  262.     for i,k in pairs(tagList) do
  263.         assigntag(i,k)
  264.     end
  265. end
  266.  
  267. tags.loadTagPatch = function(A) --
  268.     patch=getT(A) or {}
  269.     for i,k in pairs(patch) do
  270.         if not isTag(i) then createTag(i) end --if tag don't exists then create it.
  271.         for j,m in pairs(k) do
  272.             table.insert(tagList[i],m) --add new data to tag table
  273.         end
  274.         assigntag(i,k) --populate lookup tables with patch data
  275.     end
  276. end
  277.  
  278. --##     MAP DATABASE     ##--
  279.  
  280. local internamMap = {}
  281. local metay = {__index=function(f,k) f[k] = {} return f[k] end}--if no y make y and return it (placed on y table)
  282. local metax = {__index=function(f,k) f[k] = setmetatable({},metay) return f[k] end} --if no x make x and return it (placed on map table)
  283. setmetatable(internamMap,metax)
  284.  
  285. local function cleanMap() --looks trought the map and removes not valid values and empty tables. Cause its eather air or unknown and we don't care about both.
  286.     for kx,vx in pairs(internamMap) do
  287.         for ky,vy in pairs(vx) do
  288.             for kz,vz in pairs(vy) do
  289.                 if type(vz)~="table" or (type(vz)=="table" and not next(vz)) then vy[kz]=nil end
  290.             end
  291.             if not next(vy) then vx[ky]=nil end
  292.         end
  293.         if not next(vx) then internamMap[kx]=nil end
  294.     end
  295. end
  296.  
  297. local function setBlock(block,x,y,z) if type(block)=="table" then internamMap[x][y][z] = block return true end end
  298. local function getBlock(x,y,z) return internamMap[x][y][z] end --add tags in this return
  299. local function saveMap() end
  300. local function loadMap() end
  301.  
  302. map.setBlock = setBlock
  303. map.getBlock = getBlock
  304. map.saveMap = saveMap
  305. map.loadMap = loadMap
  306.  
  307. util.setAutoScan = function(A) bScanner = A and true end
  308. util.getAutoScan = function() return bScanner and true end
  309.  
  310.  
  311. --##     POINT METAMAGIC     ##--
  312.  
  313. local metaPoint
  314. metaPoint = {
  315. __index = {
  316.  
  317. copy= function(t) return setmetatable({x=t.x,y=t.y,z=t.z,xd=t.xd,zd=t.zd},metaPoint)  end,
  318.  
  319. offset = function(t,ox,oy,oz) return t.x and t.y and t.z and setmetatable({x=t.x+ox,y=t.y+oy,z=t.z+oz,xd=t.xd,zd=t.zd},metaPoint)  end,
  320. offsetL = function(t,ox,oy,oz) return t.x and t.y and t.z and t.xd and t.zd and setmetatable({x=t.x+ox*t.xd+oz*-t.zd,y=t.y+oy,z=t.z+oz*t.xd+ox*t.zd,xd=t.xd,zd=t.zd},metaPoint) end,
  321. offsetP = function(t,A) return t.offset and t:offset(A.x,A.y,A.z) end,
  322. offsetPL = function(t,A) return t.offsetL and t:offsetL(A.x,A.y,A.z) end, --local to provided point
  323.  
  324. ox = function(t,A) return t.offset and t:offset(A or 0,0,0) end,
  325. oy = function(t,A) return t.offset and t:offset(0,A or 0,0) end,
  326. oz = function(t,A) return t.offset and t:offset(0,0,A or 0) end,
  327.  
  328. up = function(t,A) return t.offset and t:offset(0,(A or 1),0) end,
  329. down = function(t,A) return t.offset and t:offset(0,-(A or 1),0) end,
  330.  
  331. forward = function(t,A) return t.offset and t.xd and t.zd and t:offset((A or 1)*t.xd,0,(A or 1)*t.zd) end,
  332. back = function(t,A) return t.offset and t.xd and t.zd and t:offset(-(A or 1)*t.xd,0,-(A or 1)*t.zd) end,
  333.  
  334. left = function(t,A) return t.offset and t.xd and t.zd and t:offset((A or 1)*t.zd,0,(A or 1)*-t.xd) end,
  335. right = function(t,A) return t.offset and t.xd and t.zd and t:offset((A or 1)*-t.zd,0,(A or 1)*t.xd) end,
  336.  
  337. turnLeft = function(t) return t.offset and t.xd and t.zd and t:offset(0,0,0):setxd(t.zd):setzd(-t.xd) end,
  338. turnRight = function(t) return t.offset and t.xd and t.zd and t:offset(0,0,0):setxd(-t.zd):setzd(t.xd) end,
  339. turnBack = function(t) return t.offset and t.xd and t.zd and t:offset(0,0,0):setxd(-t.xd):setzd(-t.zd) end,
  340.  
  341. upG = function(t,A) return t.offset and t:offset(0,(A or 1),0) end,
  342. downG = function(t,A) return t.offset and t:offset(0,-(A or 1),0) end,
  343.  
  344. forwardG = function(t,A) return t.offset and pos.xd and pos.zd and t:offset((A or 1)*pos.xd,0,(A or 1)*pos.zd) end,
  345. backG = function(t,A) return t.offset and pos.xd and pos.zd and t:offset(-(A or 1)*pos.xd,0,-(A or 1)*pos.zd) end,
  346.  
  347. leftG = function(t,A) return t.offset and pos.xd and pos.zd and t:offset((A or 1)*pos.zd,0,(A or 1)*-pos.xd) end,
  348. rightG = function(t,A) return t.offset and pos.xd and pos.zd and t:offset((A or 1)*-pos.zd,0,(A or 1)*pos.xd) end,
  349.  
  350. block = function(t) return t.x and t.y and t.z and getBlock(t.x,t.y,t.z) end,
  351. unp = function(t) return t.x,t.y,t.z,t.xd,t.zd end,
  352.  
  353. getf = function(t) if t.xd==0 and t.zd==1 then return 0
  354.         elseif t.xd==-1 and t.zd==0 then return 1
  355.         elseif t.xd==0 and t.zd==-1 then return 2
  356.         elseif t.xd==1 and t.zd==0 then return 3 end end,
  357.        
  358. setf = function(t,A) if A==0 then t.xd=0 t.zd=1 return t
  359.         elseif A==1 then t.xd=-1 t.zd=0 return t
  360.         elseif A==2 then t.xd=0 t.zd=-1 return t
  361.         elseif A==3 then t.xd=1 t.zd=0 return t end end,
  362.        
  363. setx = function(t,A) t.x=A return t end,
  364. sety = function(t,A) t.y=A return t end,
  365. setz = function(t,A) t.z=A return t end,
  366.  
  367. setxd = function(t,A) t.xd=A return t end,
  368. setzd = function(t,A) t.zd=A return t end,
  369.  
  370. clearf = function(t,A) t.zd=nil t.xd=nil return t end,
  371.  
  372. tos = function(t) return tostring(t) end,
  373. },
  374. --__newindex
  375. --__add
  376. --__sub
  377. --__mul
  378. --__div
  379. --__mod
  380. --__pow
  381. --__unm (-A)
  382. --__concat
  383.  
  384. --__len = Distance for current point to that point in shortest way possible
  385. --__eq  equal = compare coordinates and directions if they are there.
  386. --__lt  larger,smaller -->  compare fuel cost on direct route from current pos
  387. --__le - defaults to not lt so its cool
  388.  
  389. --__call
  390.  
  391. __tostring = function(t) return "["..(t.x and " x:"..t.x or "")..(t.y and " y:"..t.y or "")..(t.z and " z:"..t.z or "")..(t.xd and " xd:"..t.xd or "")..(t.zd and " zd:"..t.zd or "")..(t.getf and t:getf() and " f:"..t:getf() or "").." ]" end,
  392. --__metatable
  393.  
  394. --# 5.2 up
  395. --__ipairs
  396. --__pairs
  397.  
  398. --5.3 is ignored for now. lot of bitwise meta added.
  399. }
  400.  
  401. --##DEBUG ITEM
  402. testpoint = setmetatable({x=0,y=0,z=0,xd=0,zd=1},metaPoint)
  403.  
  404. util.makePoint = function(x,y,z,xd,zd) --make a point from coordinates
  405.     return setmetatable({["x"]=x,["y"]=y,["z"]=z,["xd"]=xd,["zd"]=zd},metaPoint)
  406. end
  407.  
  408. util.remakePoint = function(A) --make a point from table
  409.     return setmetatable(A,metaPoint)
  410. end
  411.  
  412. util.savePoint = function(A,B) --save point a into file b
  413.     saveT(B,A)
  414. end
  415. metaPoint.__index.save = util.savePoint --add it to point metatable as save
  416.  
  417. util.loadPoint = function(A)
  418.     return setmetatable(getT(A or"/gps.log"),metaPoint)
  419. end
  420.  
  421.  
  422.  
  423. --##     LOCAL POSITION     ##--
  424.  
  425. pos = setmetatable({x=0,y=0,z=0,xd=1,zd=0},metaPoint) --position of turtle
  426.  
  427. --[[savePos = function(A)
  428.     saveT(A or "/gps.log",pos)
  429. end
  430.  
  431. loadPos = function(A)
  432.     pos=setmetatable(getT(A or"/gps.log"),metaPoint) or pos
  433. end]] --allows bad coding practise. If you realy need it the uncomment it.
  434.  
  435. setPos = function(x,y,z,xd,zd) --set position to provided parameters
  436.   pos=setmetatable({["x"]=x,["y"]=y,["z"]=z,["xd"]=xd,["zd"]=zd},metaPoint)
  437.   bMovelock = false
  438. end
  439.  
  440. getPos = function() --get static table with current position
  441.  return setmetatable(copyT(pos),metaPoint)
  442. end
  443.  
  444. --##SEMI-DEBUG ITEM
  445. getPosDynamic = function() --get table that always contains current position
  446.  return setmetatable({},{__index=pos,__newindex=function() end,__tostring=metaPoint.__tostring})
  447. end
  448.  
  449. --##     MOVEMENT CONTROLS     ##--
  450.  
  451. --##INTERNAL
  452.  
  453. local function scan() --scans up forward down
  454.     local status,response,block
  455.     status,response = oldturtle.inspectUp()
  456.     if status then
  457.         block = pos:up():clearf()
  458.         setBlock(response,block:unp())
  459.     end
  460.     status,response = oldturtle.inspect()
  461.     if status then
  462.         block = pos:forward():clearf()
  463.         setBlock(response,block:unp())
  464.     end
  465.     status,response = oldturtle.inspectDown()
  466.     if status then
  467.         block = pos:down():clearf()
  468.         setBlock(response,block:unp())
  469.     end
  470. end
  471.  
  472. local function scanf() --scans just forward
  473.     local status,response,block
  474.     status,response = oldturtle.inspect()
  475.     if status then
  476.         block = pos:forward():clearf()
  477.         setBlock(response,block:unp())
  478.     end
  479. end
  480.  
  481. local function vacuum()
  482.     while turtle.suckUp() do end
  483.     while turtle.suck() do  end
  484.     while turtle.suckDown() do end
  485. end
  486.  
  487. turnRight = function(A)
  488.         if bMovelock then return false,"Unknown Position, movement locked" end
  489.         oldturtle.turnRight()
  490.         pos.xd, pos.zd = -pos.zd, pos.xd
  491.         if bScanner or A then scanf() end
  492.         if  bVacuum then vacuum() end
  493.         return true
  494. end
  495.  
  496.  
  497. turnLeft = function(A)
  498.         if bMovelock then return false,"Unknown Position, movement locked" end
  499.         oldturtle.turnLeft()
  500.         pos.xd, pos.zd = pos.zd, -pos.xd
  501.         if  bScanner or A then scanf() end
  502.         if  bVacuum then vacuum() end
  503.         return true
  504. end
  505.  
  506.  
  507. up = function(A)
  508.     bInMove = true
  509.     if bMovelock then bInMove = false return false,"Unknown Position, movement locked"
  510.     elseif oldturtle.up() or (bBrutal and oldturtle.attack() and oldturtle.up()) then
  511.         pos.y = pos.y+1
  512.         bInMove = false
  513.         if  bScanner or A then scan() end
  514.         if  bVacuum then vacuum() end
  515.         return true
  516.     else
  517.         bInMove = false
  518.         return false
  519.     end
  520. end
  521.  
  522.  
  523. down = function(A)
  524.     bInMove = true
  525.     if bMovelock then bInMove = false  return false,"Unknown Position, movement locked"
  526.     elseif oldturtle.down() or (bBrutal and oldturtle.attackDown() and oldturtle.down())then
  527.         pos.y = pos.y-1
  528.         bInMove = false
  529.         if  bScanner or A then scan() end
  530.         if  bVacuum then vacuum() end
  531.         return true
  532.     else
  533.         bInMove = false
  534.         return false
  535.     end
  536. end
  537.  
  538.  
  539. forward = function(A)
  540.     bInMove = true
  541.     if bMovelock then bInMove = false return false,"Unknown Position, movement locked"
  542.     elseif oldturtle.forward() or (bBrutal and oldturtle.attack() and oldturtle.forward()) then
  543.         pos.x = pos.x+pos.xd
  544.         pos.z = pos.z+pos.zd
  545.         bInMove = false
  546.         if  bScanner or A then scan() end
  547.         if  bVacuum then vacuum() end
  548.         return true
  549.     else
  550.         bInMove = false
  551.         return false
  552.     end
  553. end
  554.  
  555. back = function(A)
  556.     bInMove = true
  557.     if bMovelock then bInMove = false return false,"Unknown Position, movement locked"
  558.     elseif oldturtle.back() then
  559.         pos.x = pos.x-pos.xd
  560.         pos.z = pos.z-pos.zd
  561.         bInMove = false
  562.         if  bScanner or A then scan() end
  563.         if  bVacuum then vacuum() end
  564.         return true
  565.     else
  566.         bInMove = false
  567.         return false
  568.     end
  569. end
  570.  
  571.  
  572. util.setBrutal = function(A) bBrutal = A and true end
  573. util.getBrutal = function() return bBrutal and true end
  574. util.setVacuum = function(A) bVacuum = A and true end
  575. util.getVacuum = function() return bVacuum and true end
  576. util.getBrake = function() return bMovelock and true end
  577.  
  578.  
  579. --##     GPS LOCATING     ##--
  580.  
  581. gpsPos=function(A,B) --gets pos from GPS will get lost in process sometimes. -- add movement up and down.
  582.     local pos1,pos2={},{}
  583.    
  584.     if B then pos1={gps.locate(2,A)} if pos1 then setPos(pos1[1],pos1[2],pos1[3],1,0) bMovelock = true return true end end
  585.  
  586.     if getFuelLevel()<2 then return false,"Fuel Level Insufficient" end
  587.     pos1={gps.locate(2,A)}
  588.     if not pos1[1] then return false,"No GPS Signal" end
  589.    
  590.     if pos1[1] and oldturtle.forward() then
  591.         pos2={gps.locate(2,A)}
  592.         if pos2[1] then
  593.             setPos(pos2[1],pos2[2],pos2[3],pos2[1]-pos1[1],pos2[3]-pos1[3])
  594.             back()
  595.             return true
  596.         else
  597.             oldturtle.back()
  598.             return false,"GPS Signal Error"
  599.         end
  600.     elseif pos1[1] and oldturtle.back() then
  601.         pos2={gps.locate(2,A)}
  602.         if pos2[1] then
  603.             setPos(pos2[1],pos2[2],pos2[3],pos1[1]-pos2[1],pos1[3]-pos2[3])
  604.             forward()
  605.             return true
  606.         else
  607.             oldturtle.forward()
  608.             return false,"GPS Signal Error"
  609.         end
  610.     end
  611.    
  612.     oldturtle.turnLeft()
  613.    
  614.     if pos1[1] and oldturtle.forward() then
  615.         pos2={gps.locate(2,A)}
  616.         if pos2[1] then
  617.             setPos(pos2[1],pos2[2],pos2[3],pos2[1]-pos1[1],pos2[3]-pos1[3])
  618.             back()
  619.             turnRight()
  620.             return true
  621.         else
  622.             oldturtle.back()
  623.             return false,"GPS Signal Error"
  624.         end
  625.     elseif pos1[1] and oldturtle.back() then
  626.         pos2={gps.locate(2,A)}
  627.         if pos2[1] then
  628.             setPos(pos2[1],pos2[2],pos2[3],pos1[1]-pos2[1],pos1[3]-pos2[3])
  629.             forward()
  630.             turnRight()
  631.             return true
  632.         else
  633.             oldturtle.forward()
  634.             return false,"GPS Signal Error"
  635.         end
  636.     end
  637.    
  638.     oldturtle.turnRight()
  639.    
  640.     return false,"Can't move to confirm position"
  641. end
  642.  
  643. --##     INSPECT AND GETDETAIL     ##--
  644.  
  645. local function addtags(t,bDam)
  646.     local tags={}
  647.     local Worklist = copyT(lookupName[t.name] and lookupName[t.name][true],lookupName[t.name] and lookupName[t.name][t.metadata or t.damage],lookupName[t.name] and lookupName[t.name][bDam and "d"..t.damage or "m"..t.metadata]) --merge tags from main block and from metadata/damage subblock and from metadata,damage blocks depending on mode
  648.     local Modtag="#"..string.match(t.name, "^([^:]+:)") --"^([^:]+):"
  649.     Worklist[Modtag]=true
  650.     Worklist["#All"]=true --Utility tag.
  651.     local empty=false
  652.    
  653.     while not empty do
  654.         empty=true
  655.         for i in pairs(copyT(Worklist)) do --for each tag analize
  656.             empty=false
  657.             Worklist[i]=nil
  658.             tags[i]=true
  659.             Worklist=copyT(Worklist,lookupTag[i]) --add parent tags to WorkList
  660.         end
  661.     end
  662.    
  663.     t.tags=tags
  664.     return t
  665. end
  666.  
  667. inspect = function()
  668.     local status,response = oldturtle.inspect()
  669.     if status then
  670.         if not bMovelock then
  671.             local block = pos:forward():clearf()
  672.             setBlock(response,block:unp())
  673.             response.point=block
  674.         end
  675.         return status,addtags(response) --scan for m3 type tags -- boollean left as nil
  676.     else
  677.         return status,response
  678.     end
  679. end
  680.  
  681. inspectUp = function()
  682.     local status,response = oldturtle.inspectUp()
  683.     if status then
  684.         if not bMovelock then
  685.             local block = pos:up():clearf()
  686.             setBlock(response,block:unp())
  687.             response.point=block
  688.         end
  689.         return status,addtags(response) --scan for m3 type tags -- boollean left as nil
  690.     else
  691.         return status,response
  692.     end
  693. end
  694.  
  695. inspectDown = function()
  696.     local status,response = oldturtle.inspectDown()
  697.     if status then
  698.         if not bMovelock then
  699.             local block = pos:down():clearf()
  700.             setBlock(response,block:unp())
  701.             response.point=block:clearf()
  702.         end
  703.         return status,addtags(response) --scan for m3 type tags -- boollean left as nil
  704.     else
  705.         return status,response
  706.     end
  707. end
  708.  
  709. getItemDetail = function(A)
  710. local response = oldturtle.getItemDetail(A)
  711.     if response then
  712.         return addtags(response,true) --scan for d3 type tags
  713.     else
  714.         return response
  715.     end
  716. end
  717.  
  718. --##     COMPARE EXPANSION     ##--
  719.  
  720. local function comp(A,B)
  721.     if A and type(A)=="number" and A>=1 and A<=16 then
  722.         local C=oldturtle.getSelectedSlot()
  723.         oldturtle.select(A)
  724.         local D=B()
  725.         oldturtle.select(C)
  726.         return D
  727.     else
  728.         return B()
  729.     end
  730. end
  731.  
  732. compareSlot = function(A) return comp(A,oldturtle,compare) end
  733. compareSlotUp = function(A) return comp(A,oldturtle,compareUp) end
  734. compareSlotDown = function(A) return comp(A,oldturtle,compareDown) end
  735.  
  736. compareTwo = function(A,B)
  737.     local C=oldturtle.getSelectedSlot()
  738.     oldturtle.select(A)
  739.     local D=oldturtle,compareTo(B)
  740.     oldturtle.select(C)
  741.     return D
  742. end
  743.  
  744. --##     FUEL INFORMATION     ##--
  745.  
  746. local Fuellimit=term.native().isColor() and 100000 or 20000
  747.  
  748. getFuelLevel = function()
  749.     local temp=oldturtle.getFuelLevel()
  750.     return temp=="unlimited" and Fuellimit or temp
  751. end
  752.  
  753. getFuelLimit =  function()
  754.     local temp=oldturtle.getFuelLimit()
  755.     return temp=="unlimited" and Fuellimit or temp
  756. end
  757.  
  758. getFuelPercent = function()
  759.     return getFuelLevel()/getFuelLimit()
  760. end
  761.  
  762. getFuelSpace = function()
  763.     return getFuelLimit()-getFuelLevel()
  764. end
  765.  
  766. --##     SMART REFUEL     ##--
  767.  
  768. refuel = function(A) --limit aware refuel
  769.     A = A or 1000
  770.     if A==0 or not oldturtle.refuel(0) then return oldturtle.refuel(0) end
  771.     local current=getFuelLevel()
  772.     local value=0
  773.     if getFuelPercent()<1 then
  774.         oldturtle.refuel(1)
  775.         A=A-1
  776.         value=getFuelLevel()-current
  777.         local toRefuel=math.min(A,math.max(math.ceil(getFuelSpace()/value),0),oldturtle.getItemCount()) --64)
  778.         if toRefuel > 0 then oldturtle.refuel(toRefuel) end
  779.     end
  780.     return true
  781. end
  782.  
  783. --##     DIG AND PLACE BLACKLIST/WHITELIST     ##--
  784.  
  785. ------------------------------------------------------------ADD bScanner block,t = A() setBlock(t.point:unp(),nil)
  786.  
  787. local function di(A,B)
  788.     local block,t = A()
  789.     if block then
  790.         --scan for whitelist tag
  791.         if t.tags and t.tags["#DigWhitelist"] then return B() end
  792.         --scan blacklist
  793.         if t.tags and t.tags["#DigBlacklist"] then return false,"Blacklisted" end
  794.         --do it normally
  795.         return B()
  796.     else
  797.     return false,"Nothing to dig here"
  798.     end
  799. end
  800.  
  801. dig = function() return di(inspect,oldturtle.dig) end
  802. digUp = function() return di(inspectUp,oldturtle.digUp) end
  803. digDown = function() return di(inspectDown,oldturtle.digDown) end
  804.  
  805. ------------------------------------------------------------ADD bScanner block,t = A() setBlock(t.point:unp(),nil)
  806.  
  807. local function pi(A,B)
  808.     local t = getItemDetail()
  809.     if t then
  810.         --scan for whitelist tag
  811.         if t.tags and t.tags["#PlaceWhitelist"] then return A(B) end
  812.         --scan blacklist
  813.         if t.tags and t.tags["#PlaceBlacklist"] then return false,"Blacklisted" end
  814.         --do it normally
  815.         return A(B)
  816.     else
  817.     return false,"No items to place"
  818.     end
  819. end
  820.  
  821. place = function(A) return pi(oldturtle.place,A) end
  822. placeUp = function() return pi(oldturtle.placeUp) end
  823. placeDown = function() return pi(oldturtle.placeDown) end
  824.  
  825. --##     PATHFINGING     ##--
  826.  
  827. --Mode 3/4
  828.  
  829. local function upP(A,B,C) --A-Size, B-Scanning, C-Dig
  830.    
  831.     for i=1,A do
  832.    
  833.         if up(B) or (C and digUp() and up(B)) then
  834.             return true
  835.         else
  836.        
  837.             if math.random(0,1)==1 then
  838.                 if forward(B) or (C and dig() and forward(B)) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if up(B) or (C and digUp() and up(B)) then return true end end
  839.             else
  840.                 if turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if up(B) or (C and digUp() and up(B)) then return true end end
  841.             end
  842.            
  843.             turnLeft(B)
  844.            
  845.             if math.random(0,1)==1 then
  846.                 if forward(B) or (C and dig() and forward(B)) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if up(B) or (C and digUp() and up(B)) then return true end end
  847.             else
  848.                 if turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if up(B) or (C and digUp() and up(B)) then return true end end
  849.             end
  850.            
  851.         end
  852.     end
  853.    
  854.     return false
  855. end
  856.  
  857. local function downP(A,B,C)
  858.  
  859.     for i=1,A do
  860.    
  861.         if down(B) or (C and digDown() and down(B)) then
  862.             return true
  863.         else
  864.        
  865.             if math.random(0,1)==1 then
  866.                 if forward(B) or (C and dig() and forward(B)) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if down(B) or (C and digDown() and down(B)) then return true end end
  867.             else
  868.                 if turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if down(B) or (C and digDown() and down(B)) then return true end end
  869.             end
  870.            
  871.             turnLeft(B)
  872.            
  873.             if math.random(0,1)==1 then
  874.                 if forward(B) or (C and dig() and forward(B)) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if down(B) or (C and digDown() and down(B)) then return true end end
  875.             else
  876.                 if turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) or turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then if down(B) or (C and digDown() and down(B)) then return true end end
  877.             end
  878.            
  879.         end
  880.     end
  881.    
  882.     return false
  883. end
  884.  
  885. local function forwardP(A,B,C)
  886.    
  887.     for i=1,A do
  888.    
  889.         if forward(B) or (C and dig() and forward(B)) then
  890.             return true
  891.         else
  892.        
  893.             if math.random(0,1)==1 then
  894.                 if up(B) or down(B) or (C and digUp() and up(B)) or (C and digDown() and down(B)) then if forward(B) or (C and dig() and forward(B)) then return true end end
  895.             else
  896.                 if down(B) or up(B) or (C and digDown() and down(B)) or (C and digUp() and up(B)) then if forward(B) or (C and dig() and forward(B)) then return true end end
  897.             end
  898.            
  899.             local dir=math.random(0,1)
  900.            
  901.             if dir == 1 then turnLeft(B) else turnRight(B) end
  902.            
  903.             if forward(B) or (C and dig() and forward(B)) then
  904.                 if dir == 1 then turnRight(B) else turnLeft(B) end
  905.                 if forward(B) or (C and dig() and forward(B)) then return true end
  906.             elseif turnLeft(B) and turnLeft(B) and (forward(B) or (C and dig() and forward(B))) then           
  907.                 if dir == 1 then turnLeft(B) else turnRight(B) end
  908.                 if forward(B) or (C and dig() and forward(B)) then return true end
  909.             end
  910.            
  911.         end
  912.     end
  913.    
  914.     return false
  915.  
  916. end
  917.  
  918. local function backP(A,B,C) --add back pathfinding as forward one with 180 reverse first later
  919.     turnLeft(B)
  920.     turnLeft(B)
  921.     return forwardP(A,B,C)
  922. end
  923.  
  924. --Map based
  925.  
  926. --use binary to store blocked directions? Inspect everything
  927. --if somepalce has only one way in then its 1? that means its blocked.
  928. --blocked place is like a block you can't break - so in tunnel it would spread until whole tunnel got marked as blocked.
  929. --instead of going to the place you want to go go 1 block in direction that is not blocked but still leads forard to target.
  930. --problem - big holes  that are blocked - need to figure them out.
  931.    
  932.  
  933. --##     GOTO     ##--
  934.  
  935. local function face(A,B,C)
  936.     if pos.xd==A and pos.zd==B then return end
  937.     if pos.zd==A and -pos.xd==B then turnLeft(C) return end
  938.     if -pos.zd==A and pos.xd==B then turnRight(C) return end
  939.     if -pos.xd==A or -pos.zd==B then turnRight(C) turnRight(C) return end
  940. end
  941.  
  942. util.face = face
  943.  
  944. local function fromTo(...) --Distance between 2 points. If given more than 2 points it will claculate minimal fuel to go from first to last in order given
  945.     local tArgs={...}
  946.     if #tArgs==1 then return 0
  947.     elseif #tArgs==2 then return math.abs((tArgs[1].x-tArgs[2].x)) + math.abs((tArgs[1].y-tArgs[2].y)) + math.abs((tArgs[1].z-tArgs[2].z))
  948.     else return fromTo(tArgs[1],tArgs[2])+fromTo(unpack(tArgs,2)) end
  949. end
  950.  
  951. util.fromTo = fromTo
  952. metaPoint.__index.fromTo = fromTo
  953.  
  954. local function fromTo2d(...) --Distance between 2 points. If given more than 2 points it will claculate minimal fuel to go from first to last in order given. Ignores height.
  955.     local tArgs={...}
  956.     if #tArgs==1 then return 0
  957.     elseif #tArgs==2 then return math.abs((tArgs[1].x-tArgs[2].x)) + math.abs((tArgs[1].z-tArgs[2].z))
  958.     else return fromTo2d(tArgs[1],tArgs[2])+fromTo2d(unpack(tArgs,2)) end
  959. end
  960.  
  961. util.fromTo2d = fromTo2d
  962. metaPoint.__index.fromTo2d = fromTo2d
  963.  
  964.  
  965. local moves = {} --1 goto, 2 goto + mine obscales, 3 goto + pathfind1, 4 goto + mine obscales then pathfind1 if mine failed, 5 - planned - goto + pathfind then mine if pathfind failed.
  966. moves[1] = {
  967.         ["up"] = function(C,D) return up(D) end,
  968.         ["forward"] = function(C,D) return forward(D) end,
  969.         ["down"] = function(C,D) return down(D) end,
  970. }
  971. moves[2] = {
  972.         ["up"] = function(C,D) if not up(D) then return digUp() else return true end end,
  973.         ["forward"] = function(C,D) if not forward(D) then return dig() else return true end end,
  974.         ["down"] = function(C,D) if not down(D) then return digDown() else return true end end,
  975. }
  976. moves[3] = {
  977.         ["up"] = function(C,D)  return upP(C,D) end,
  978.         ["forward"] = function(C,D)  return forwardP(C,D) end,
  979.         ["down"] = function(C,D)  return downP(C,D) end,
  980. }
  981. moves[4] ={ --make upPD downPD forwardPD backPD
  982.         ["up"] = function(C,D) if not up(D) then digUp() return upP(C,D,true) else return true end end,
  983.         ["forward"] = function(C,D)  if not forward() then dig() return forwardP(C,D,true) else return true end end,
  984.         ["down"] = function(C,D)  if not down(D) then digDown() return downP(C,D,true) else return true end end,
  985. }
  986.  
  987. local function BlackTest() -- tests if block you are going to is blacklisted.
  988.  
  989. end
  990.  
  991. goto = function(A,B,C,D) --A target point, B move mode, C used only for pathfinding - defines how far turtle will move from start point, D Force scanning for duration of goto.
  992.    
  993.     if A and type(A) == "table" and A.x and A.y and A.z and type(A.x)== "number" and type(A.y)== "number" and type(A.z)== "number" then
  994.         B=B or 1 --B=1 is default if B not defined
  995.         C=C or 5 --C=5 is default if C not defined
  996.         D = true
  997.        
  998.         local move = moves[B]
  999.         if not move then
  1000.             error("Illegal movement mode selected.",1)
  1001.         end
  1002.  
  1003.         while A.x-pos.x ~= 0 or A.y-pos.y ~= 0 or A.z-pos.z ~= 0 do
  1004.            
  1005.             if getFuelLevel()<fromTo(A,pos) then return false,"Fuel Level Insufficient" end
  1006.            
  1007.             --going up always takes priority
  1008.             if A.y-pos.y > 0 then while A.y-pos.y ~= 0 do if not move.up(C,D) then break end end end
  1009.            
  1010.             if A.x-pos.x < 0 then face(-1,0) while A.x-pos.x ~= 0 and pos.xd==-1 and pos.zd==0 do if not move.forward(C,D) then break end end  end
  1011.             if A.x-pos.x > 0 then face(1,0) while A.x-pos.x ~= 0 and pos.xd==1 and pos.zd==0 do if not move.forward(C,D) then break end  end  end
  1012.            
  1013.             if A.z-pos.z < 0 then face(0,-1) while A.z-pos.z ~= 0 and pos.xd==0 and pos.zd==-1 do if not move.forward(C,D) then break end end  end
  1014.             if A.z-pos.z > 0 then face(0,1) while A.z-pos.z ~= 0 and pos.xd==0 and pos.zd==1 do if not move.forward(C,D) then break end end end
  1015.            
  1016.             if A.y-pos.y < 0 then while A.y-pos.y ~= 0 do if not move.down(C,D) then break end end end
  1017.            
  1018.             sleep(0.05)
  1019.         end
  1020.     else
  1021.         return false,"Invalid point"
  1022.     end
  1023.    
  1024.     if A.xd and A.zd then
  1025.         face(A.xd,A.zd)
  1026.     end
  1027.  
  1028.     return true
  1029.    
  1030. end
  1031. metaPoint.__index.goto = goto
  1032.  
  1033.  
  1034. --##     Daemon     ##--  
  1035. --Only if _WojbieStarter = true
  1036.  
  1037. if _WojbieStarter then
  1038.     local bRunning = false
  1039.    
  1040.     local bOn = false
  1041.     local nCur = false
  1042.    
  1043.     runDaemon = function(apiName,apiTable) --deamon version for custom coorutine menager. Works like rednet.run
  1044.         if bRunning then
  1045.             error( "Daemon is already running", 2 )
  1046.         end
  1047.         bRunning = true
  1048.        
  1049.         --load patches from .tPatch/
  1050.         if fs.exists("/.tPatch") and fs.isDir("/.tPatch") then
  1051.             for i,k in pairs(fs.list("/.tPatch")) do
  1052.                 tags.loadTagPatch(fs.combine("/.tPatch",k))
  1053.             end
  1054.         end
  1055.        
  1056.         --Modem watchdog - ensures that gps chanel is always open.
  1057.         local sModemSide = nil
  1058.        
  1059.         local function testModem() -- Find a modem
  1060.             if sModemSide and peripheral.getType( sModemSide ) == "modem" and peripheral.call( sModemSide, "isWireless" ) and peripheral.call( sModemSide, "isOpen" , gps.CHANNEL_GPS) then
  1061.                 return true
  1062.             end
  1063.             sModemSide = nil
  1064.             for n,sSide in ipairs( rs.getSides() ) do
  1065.                 if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then  
  1066.                     local ok = pcall(peripheral.call,sSide, "open" , gps.CHANNEL_GPS) --overdrawing on channels test.
  1067.                     if ok then sModemSide = sSide break end
  1068.                 end
  1069.             end
  1070.             return sModemSide and true
  1071.         end
  1072.        
  1073.         -- Open a channel
  1074.  
  1075.         --Main daemon part - GPS host and fuel labeler.
  1076.         local tEvents
  1077.         local timer = os.startTimer(1)
  1078.        
  1079.         while true do
  1080.             tEvents={os.pullEventRaw()}
  1081.            
  1082.             --Gps responding
  1083.             --"modem_message" Side Channel ReplyChannel Message Distance
  1084.             if bOn and (not bInMove) and tEvents[1] == "modem_message" and testModem() and tEvents[2] == sModemSide and tEvents[3] == gps.CHANNEL_GPS and tEvents[5] == "PING" then
  1085.                 peripheral.call( sModemSide, "transmit", tEvents[4] , gps.CHANNEL_GPS, { pos.x, pos.y, pos.z } )
  1086.            
  1087.             --Local turtle menagement.
  1088.             --"timer nTimer
  1089.             elseif tEvents[1] == "timer" and tEvents[2] == timer then
  1090.                 timer = os.startTimer(1)
  1091.                  --Retesting modem.
  1092.                 if bOn then testModem() end
  1093.                  --Retesting fuel label.
  1094.                 if nCur and os.getComputerLabel() and nCur ~= getFuelPercent() then os.setComputerLabel((string.match(os.getComputerLabel(),"^(.+) %[[%d%.]-%%%]$") or os.getComputerLabel()).." ["..(math.floor(turtle.getFuelPercent()*1000)/10).."%]") nCur = getFuelPercent() end end
  1095.         end
  1096.     end
  1097.    
  1098.     util.setDaemonGps = function(A) bOn = A and true end
  1099.     util.getDaemonGps = function() return bOn and true end
  1100.     util.setFuelLabel = function(A) if A and os.getComputerLabel() then nCur = -1 elseif os.getComputerLabel() then os.setComputerLabel(string.match(os.getComputerLabel(),"^(.+) %[[%d%.]-%%%]$") or os.getComputerLabel()) nCur = false end end
  1101.     util.getFuelLabel = function() return nCur and true end
  1102.    
  1103. end
  1104.  
  1105. --##     PERIPHERAL FIXER     ##--
  1106. util.peripheralFix = function()
  1107. --Detect
  1108. --Fix
  1109. --End
  1110. end
  1111.  
  1112. --##     TURTLE FUNCTIONS DUPLICATOR     ##--
  1113. --in case this api is loaded onto turtle api.
  1114.  
  1115. local env = _ENV
  1116. for k,v in pairs( oldturtle ) do
  1117.     if not rawget(env, k) then env[k] = v end -- place the value defined before or use oldturtle one
  1118. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement