Advertisement
vedalken254

Module API

Apr 16th, 2014
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 23.09 KB | None | 0 0
  1. -- module API by PonyKuu (Revision by vedalken254 for CC 1.62 with help from Bomb Bloke and wojbie on CC Forums.)
  2. -- Version 0.2.1Alpha
  3.  
  4. -- A little change to standard assert function
  5. _G.assert = function(condition, errMsg, level)
  6.     if not condition then
  7.         error(errMsg, (tonumber(level) or 1) + 1)
  8.     end
  9.     return condition
  10. end
  11.  
  12. --[[
  13. *********************************************************************************************
  14. *                                    Communication Part                                     *
  15. *********************************************************************************************
  16. ]]--
  17. -- There are some variables used for communication
  18. -- ID is the turtle's unique identifier
  19. -- Master is the ID of the master
  20. -- Channel is the channel used to send messages to Master
  21. -- Master should respond on channel+1
  22. -- Type is the type of the module. Used by Master to determine what it can do
  23. local ID = 0
  24. local Master = 0
  25. local channel = 100
  26. local Type = "default"
  27.  
  28. function setType (newType)
  29.     assert (type(newType) == "string", "Bad module type: String required", 2)
  30.     Type = newType
  31. end
  32.  
  33. -- Wee need a modem to communicate.
  34. local modem = peripheral.wrap ("right")
  35.  
  36. -- The first function is used to parse a message received on modem
  37. -- It determines whether the message is valid or not
  38. -- Message should be a table with fields
  39. --  1) Protocol - must be equal to "KuuNet"
  40. --  2) ID - that must be equal to turtle's ID
  41. --  3) Master - that must be equal to Master variable.
  42. --  Some other fiels
  43. local function isValid (message)
  44.     return  message ~= nil and
  45.             type(message) == "table" and
  46.             message.Protocol == "SwarmNet" and
  47.             message.ID == ID and
  48.             message.Master == Master
  49. end
  50.  
  51. -- This function sends a request to Master and waits for a response.
  52. -- Request is just a simple string
  53. -- It returns response as message or nil
  54. function request (message, timeout)
  55.     assert (type(message) == "string", "Bad message: String required, got "..type(message), 2)
  56.     assert (type(timeout) == "number", "Bad timeout: Number required, got "..type(timeout), 2)
  57.     -- open a channel to listen for response
  58.     modem.open (channel+1)
  59.     -- Make a message
  60.     local request = {
  61.         Protocol = "SwarmNet",
  62.         ID = ID,
  63.         Type = Type,
  64.         Master = Master,
  65.         Request = message
  66.     }
  67.     -- And send it!
  68.     modem.transmit (channel, channel+1, textutils.serialize(request))
  69.     local response = nil
  70.     -- Wait for a valid message as response until the timeout
  71.     parallel.waitForAny (
  72.         function ()
  73.             sleep (timeout)
  74.         end,
  75.             function ()
  76.                 while true do
  77.                 local _, _, _, _, textMessage = os.pullEvent("modem_message")
  78.                 local msg = textutils.unserialize (textMessage)
  79.                 if isValid(msg) then
  80.                     response = msg
  81.                     break
  82.                 end
  83.             end
  84.         end
  85.     )
  86.     modem.close (channel+1)
  87.     return response
  88. end
  89.  
  90. --[[
  91. *********************************************************************************************
  92. *                                    Navigation Part                                        *
  93. *********************************************************************************************
  94. ]]--
  95.  
  96. -- Navigation variables.
  97.  
  98. -- Location is a global table containing all the coordinates and facing direction of the turtle
  99. local location = {x = 0, y = 0, z = 0, f = 0}
  100. -- naviData is the table used to organize the navigation of the modules so they don't lock one another movement
  101. -- Details are explaind a bit later
  102. local naviData = {x = 0, z = 0, height = 0}
  103.  
  104. -- This is the variable used to store the numbers of slots, where Ender Chests are located. Fuel chest is used to refuel the turtle, and
  105. -- Stuff chest is used to dump all the stuff mined by turtle. You can switch it off simply by setting the corresponding field to nil
  106. local chests = {Fuel = 1, Stuff = 2}
  107.  
  108. -- Here is the function to set the position of the turtle and another one to get it.
  109. function setPosition (newPosition)
  110.     assert (type(newPosition) == "table", "Bad position: Table required, got "..type(newPosition), 2)
  111.     for key, value in pairs(location) do
  112.         assert (type(value) == "number", "Bad coordinate "..key..": Number required, got "..type(value), 2)
  113.         location[key] = value
  114.     end
  115. end
  116.  
  117. function getPosition ()
  118.     return {x = location.x,
  119.             y = location.y,
  120.             z = location.z,
  121.             f = location.f,} -- return a copy of the location table.
  122. end
  123.  
  124. -- And a small function to print the position. For debug purposes
  125. function printPosition ()
  126.     print ("Currrent turtle position:")
  127.     print ("    x = "..location.x)
  128.     print ("    y = "..location.y)
  129.     print ("    z = "..location.z)
  130.     print ("    f = "..location.f)
  131. end
  132.  
  133. -- A functions to set and get the navigation data.
  134. function setNaviData (newNaviData)
  135.     assert (type(newNaviData) == "table", "Bad navigation data: Table required, got "..type(newNaviData), 2)
  136.     naviData = newNaviData
  137. end
  138. function getNaviData ()
  139.     return naviData
  140. end
  141.  
  142. -- A function to set the chest configuration
  143. function setChests (newConfiguration)
  144.     assert (type(newConfiguration) == "table", "Bad chests configuration: Table required, got "..type(newConfiguration), 2)
  145.     for chest, slot in pairs(newConfiguration) do
  146.         assert (type(slot) == "number" and slot > 0 and slot < 17, "Bad chest field "..chest.." : Not a slot number", 2)
  147.         chests [chest] = slot
  148.     end
  149. end
  150.  
  151. -- Now let's move on to our navigation functions
  152.  
  153. -- A simple turning function. tTurns is used to chech whether the argument is valid
  154. local tTurns = {left = true, right = true, around = true}
  155. function turn (direction)
  156.     assert (type(direction) == "string", "Bad direction. String required, got ".. type(direction), 2)
  157.     assert (tTurns[direction], "Bad turn direction. Turn directions are \"left\", \"right\" and \"around\", got "..direction, 2)
  158.     if direction == "left" then
  159.         turtle.turnLeft()
  160.         location.f = location.f - 1
  161.     elseif direction == "right" then
  162.         turtle.turnRight()
  163.         location.f = location.f + 1
  164.     elseif direction == "around" then
  165.         turtle.turnLeft()
  166.         turtle.turnLeft()
  167.         location.f = location.f - 2
  168.     end
  169.     location.f = (location.f + 4) % 4 -- This is used to handle the f < 0 and f > 3 situations
  170.     return true
  171. end
  172.  
  173. -- This one is used to turn the turtle to specified f direction.
  174. -- A little bit of pony magic is used to calculate how should it turn
  175. function turnTo (face)
  176.     assert (type (face) == "number", "Bad f direction. Number required, got "..type (face), 2)
  177.     assert (face >= 0 and face < 4, "Bad f direction. Required integer between 0 and 3, got "..face, 2)
  178.     local diff = face - location.f
  179.     if math.abs(diff) == 2 then --this is true if the difference between f and face is 2 or -2, so it should turn around
  180.         return turn ("around")
  181.     elseif math.fmod(diff + 4, 4) ==  1 then    --this is true if the difference between f and face is 1
  182.             return turn ("right")                   --f = 0 and face = 3 is also satisfies the condition (-3 + 4 == 1)
  183.     elseif math.fmod(diff - 4, 4) == -1 then    --this is true if the difference between f and face is -1
  184.             return turn ("left")                    --f = 3 and face = 1 is also satisfies the condition ( 3 - 4 == 1)
  185.     end
  186.     return false    --returned if turtle is already faced the specified direction
  187. end
  188.  
  189. -- This function is used to return actual x and z shifts
  190. -- These shifts are the numbers which you should add to the coordinates when turtle moves forward.
  191. -- I use a table to decode it since it is more compact and easier to read than lots of conditions
  192. local tShifts = {
  193.     [0] = { 1,  0},
  194.     [1] = { 0,  1},
  195.     [2] = {-1,  0},
  196.     [3] = { 0, -1},
  197. }
  198. local function fDirection ()
  199.     return unpack (tShifts[location.f])
  200. end
  201.  
  202. -- This function is used to update the turtle location when it has moved
  203. local function updateLocation (direction)
  204.     if direction == "up" then
  205.         location.y = location.y + 1
  206.     elseif direction == "down" then
  207.         location.y = location.y - 1        
  208.     elseif direction == "forward" then
  209.         local xShift, zShift = fDirection ()
  210.         location.x = location.x + xShift        
  211.         location.z = location.z + zShift
  212.     end
  213. end
  214.  
  215. -- This function helps us with our EnderChests if there is something that obstructs placement
  216. -- It checks what's going on on top of it, and if there is a turtle, it waits.
  217. local function forcePlaceUp ()
  218.     while not turtle.placeUp() do
  219.         if turtle.detectUp() then
  220.             if peripheral.isPresent ("top") and peripheral.getType ("top") == "turtle" then
  221.                 print "Other turtle detected. Waiting..."
  222.                 while peripheral.isPresent ("top") do
  223.                     sleep (2)
  224.                 end
  225.             end
  226.             turtle.digUp()
  227.         elseif turtle.attackUp() then
  228.             print "Attacking obstructing entity"
  229.         end
  230.     end
  231. end
  232.  
  233. -- This function tries to refuel the turtle to make it have an <amount> of fuel
  234. -- If it can't, it waits
  235. -- It also returns true if fuel is infinity
  236. function checkFuel (amount)
  237.     assert (type(amount) == "number", "Bad fuel amount. Number required, got "..type(amount), 2)
  238.     local fuel = turtle.getFuelLevel()
  239.     if fuel == "unlimited" or fuel > amount then
  240.         return true
  241.     else
  242.         turtle.select (chests.Fuel)
  243.         forcePlaceUp ()
  244.         turtle.suckUp ()
  245.         while true do
  246.             if not turtle.refuel (1) then
  247.                 if turtle.getItemCount (chests.Fuel) then
  248.                     turtle.dropUp ()
  249.                 end
  250.                 sleep (1)
  251.                 turtle.suckUp ()
  252.             end
  253.             if turtle.getFuelLevel () >= amount then
  254.                 if turtle.getItemCount (chests.Fuel) > 0 then
  255.                     turtle.dropUp ()
  256.                 end
  257.                 -- If it can't drop all the fuel into chest, just consume it all
  258.                 if turtle.getItemCount (chests.Fuel) > 0 then
  259.                     turtle.refuel (turtle.getItemCount(chests.Fuel))
  260.                 end
  261.                 turtle.digUp ()
  262.                 turtle.select (1)
  263.                 return true
  264.             end
  265.             sleep (1)
  266.         end
  267.     end
  268. end
  269.  
  270. -- This function used to empty the turtle's inventory into the ender chest in the second slot
  271. -- Warning! Required a good sorting system able to empty the chest as quickly as possible!
  272. -- It does something only if chests.Stuff is set
  273. function dumpStuff ()
  274.     if chests.Stuff ~= nil then
  275.         turtle.select (chests.Stuff)
  276.         forcePlaceUp ()
  277.         for i = 1,16 do
  278.             if i ~= chests.Fuel and i ~= chests.Stuff then
  279.                 while turtle.getItemCount (i) > 0 do
  280.                     turtle.select (i)
  281.                     turtle.dropUp ()
  282.                 end
  283.             end
  284.         end
  285.         turtle.select (chests.Stuff)
  286.         turtle.digUp ()
  287.         turtle.select (1)
  288.     end
  289. end
  290.  
  291. -- This function checks if there is any empty slots in inventory (basically, in 16th slot)
  292. function checkSpace ()
  293.     if turtle.getItemCount (16) > 0 then
  294.         dumpStuff ()
  295.     end
  296. end
  297.  
  298. -- Advanced movement function.
  299. -- Again, I use a set of tables with all the movements and other "directional" turtle actions
  300. -- The fuction detects if there is a turtle in the direction it wants to move, and if there is one, it waits while it moves away.
  301. -- If it waits too long (60 seconds), however, it just eats that turtle
  302. tMove = {
  303.     forward = turtle.forward,
  304.     up = turtle.up,
  305.     down = turtle.down
  306. }
  307. tDetect = {
  308.     forward = turtle.detect,
  309.     up = turtle.detectUp,
  310.     down = turtle.detectDown
  311. }
  312. tDig = {
  313.     forward = turtle.dig,
  314.     up = turtle.digUp,
  315.     down = turtle.digDown
  316. }
  317. tAttack = {
  318.     forward = turtle.attack,
  319.     up = turtle.attackUp,
  320.     down = turtle.attackDown
  321. }
  322. tIsTurtle = {
  323.     forward = function ()
  324.         if peripheral.isPresent ("front") and peripheral.getType ("front") == "turtle" then
  325.             return true
  326.         end
  327.         return false
  328.     end,
  329.     up = function ()
  330.         if peripheral.isPresent ("top") and peripheral.getType ("top") == "turtle" then
  331.             return true
  332.         end
  333.         return false
  334.     end,
  335.     down = function ()
  336.         if peripheral.isPresent ("bottom") and peripheral.getType ("bottom") == "turtle" then
  337.             return true
  338.         end
  339.         return false
  340.     end
  341. }
  342. function move (direction)
  343.     assert (type(direction) == "string", "Bad move direction. String required, got "..type(direction), 2)
  344.     assert (tMove[direction], "Bad move direction. Move directions are \"up\", \"down\" and \"forward\", got"..direction, 2)
  345.     -- First, check whether we have fuel to move
  346.     if not checkFuel (1) then
  347.         return false
  348.     end
  349.     -- Second, try to move
  350.     while not tMove[direction]() do
  351.         -- If can't, check if there is a block
  352.         if tDetect[direction]() then
  353.             -- If it's a turtle, just wait while it moves away.
  354.             -- WARNING! This may cause turtle interlocks!
  355.             if tIsTurtle[direction]() then
  356.                 print "Other turtle detected. Waiting..."
  357.                 while tIsTurtle[direction]() do
  358.                     sleep (2)
  359.                 end
  360.             else
  361.             -- If it's not a turtle, try to dig that block
  362.                 if tDig[direction]() then
  363.                     checkSpace ()
  364.                 -- If we can't - we just can't move.
  365.                 else
  366.                     print "Can't pass the obstruction!"
  367.                     return false
  368.                 end
  369.             end
  370.         -- If it's not a block, that's probably an entity, so we attack it!
  371.         elseif tAttack[direction]() then
  372.             checkSpace ()
  373.         end
  374.     end
  375.     -- If moved successfully, update the coordinates and return true
  376.     updateLocation (direction)
  377.     return true
  378. end
  379.  
  380. -- This one is used to move turtle to specified f direction OR up/down <count times>
  381. function moveEx (direction, count)
  382.     assert (type(direction) == "number" or type(direction) == "string", "Bad direction. String or number required, got "..type(direction), 2)
  383.     assert (type(count) == "number", "Bad count. Positive number required, got "..type(count), 2)
  384.     assert (count > 0, "Bad count. Positive number required, got "..count, 2)
  385.     if type(direction) == "number" then
  386.         assert (direction >= 0 and direction < 4, "Bad direction. Numeric direction should be between 0 and 3, got "..direction)
  387.         turnTo (direction)
  388.         for i = 1, count do
  389.             move ("forward")
  390.         end
  391.     else
  392.         assert (direction == "up" or direction == "down", "Bad direction. String direction should either \"up\" or \"down\", got "..direction, 2)
  393.         for i = 1, count do
  394.             move (direction)
  395.         end
  396.     end
  397. end
  398.  
  399. -- A height function. For convinience
  400. function height (value)
  401.     assert (type(value) == "number", "Bad value. Integer required, got "..type(value), 2)
  402.     assert (value % 1 == 0, "Bad value. Integer required, got "..value, 2)
  403.     local diff = value - location.y
  404.     checkFuel(math.abs(diff))
  405.     if diff > 0 then
  406.         moveEx ("up", diff)
  407.     elseif diff < 0 then
  408.         moveEx ("down", -diff)
  409.     end
  410. end
  411.  
  412. -- Small goto function. It moves turtle in one axis.
  413. -- Example: module.gotoOne ("x", 10) moves the turtle to x = 10
  414. -- tCoordinates is used to check if the coordinate is valid
  415. local tCoordinates = {x = true, y = true, z = true}
  416. function gotoOne (coordinate, value)
  417.     assert (type(coordinate) == "string", "Bad coordinate. String required, got "..type(coordinate), 2)
  418.     assert (tCoordinates[coordinate], "Bad coordinate. Coordinates are \"x\", \"y\" and \"z\", got "..coordinate, 2)
  419.     assert (type(value) == "number", "Bad value. Integer required, got "..type(value), 2)
  420.     assert (value % 1 == 0, "Bad value. Integer required, got "..value, 2)
  421.     if coordinate == "y" then
  422.         height (value)
  423.     elseif coordinate == "x" then
  424.         local diff = value - location.x
  425.         checkFuel(math.abs(diff))
  426.         if diff > 0 then
  427.             moveEx (0, diff)
  428.         elseif diff < 0 then
  429.             moveEx (2, -diff)
  430.         end
  431.     elseif coordinate == "z" then
  432.         local diff = value - location.z
  433.         checkFuel(math.abs(diff))
  434.         if diff > 0 then
  435.             moveEx (1, diff)
  436.         elseif diff < 0 then
  437.             moveEx (3, -diff)
  438.         end
  439.     end
  440. end
  441.  
  442. -- Let's organize our movement a bit to avoid movement deadlocks. Thanks to Doyle3694 for the idea
  443. -- It is 2D navigation, so height is not taken into account. It will allow turtles to relocate themselves to their mining positions
  444. -- without stucking.
  445. -- I'll divide all the 2D area to four zones. In each zone turtle can move only in two directions.
  446. -- Zones are determinated by the pair of coordinates. Turtles will move clockwise relative to the point with that coordinates
  447. -- height is the height at which all navigation is done
  448.  
  449. -- There is a table used to determine to which directions turtle is allowed to move.
  450. -- Direction "first" is the direction turtle will move first ^_^ This one can't lead out of the zone.
  451. -- Direction "second" is leading to the next zone.
  452. -- Directions are the tables of coordinate and direction (+1 - positive, -1 - negative)
  453. local tZones = {
  454.     z1 = {first = {"x",  1}, second = {"z",  1}},
  455.     z2 = {first = {"z",  1}, second = {"x", -1}},
  456.     z3 = {first = {"x", -1}, second = {"z", -1}},
  457.     z4 = {first = {"z", -1}, second = {"x",  1}}
  458. }
  459.  
  460. -- Here is a function to determine in which zone turtle is
  461. local function currentZone ()
  462.     if location.x > naviData.x then
  463.         if location.z > naviData.z then
  464.             return "z2"
  465.         else
  466.             return "z1"
  467.         end
  468.     else
  469.         if location.z > naviData.z then
  470.             return "z3"
  471.         else
  472.             return "z4"
  473.         end
  474.     end
  475. end
  476.  
  477. -- And there is one used to navigate turtle, taking into account zones.
  478. -- All the navigation is done at naviData.height and then turtle changes it's height
  479. function highwayNavigate (destination)
  480.     -- check destination
  481.     assert (type(destination) == "table", "Bad destination. Table required, got "..type(destination), 2)
  482.     local tCoordinates = {"x", "y", "z", "f"}
  483.     for i, coordinate in ipairs (tCoordinates) do
  484.         assert (type(destination[coordinate]) == "number", "Bad destination parameter: "..coordinate..". Integer required, got "..type(destination[coordinate]), 2)
  485.         assert (destination[coordinate] % 1 == 0, "Bad destination parameter: "..coordinate..". Integer required, got "..destination[coordinate], 2)
  486.     end
  487.     -- check navigation data
  488.     for key, value in pairs (naviData) do
  489.         assert (type(value) == "number", "Bad navigation parameter: "..key..". Number required, got "..type(value), 2)
  490.         assert (value % 1 == 0, "Bad navigation parameter: "..key..". Integer required, got "..value, 2)
  491.     end
  492.     -- go to naviData.height only if we need to move
  493.     if destination.x ~= location.x or destination.z ~= location.z then
  494.         height (naviData.height)
  495.     end
  496.     while location.x ~= destination.x or location.z ~= destination.z do -- navigate between zones until we are in the place
  497.         local zone = currentZone ()
  498.         -- Let's unpack all the coordinates
  499.         local coordinateFirst, directionFirst = unpack (tZones[zone].first)  
  500.         local coordinateSecond, directionSecond = unpack (tZones[zone].second)
  501.         -- And check some things
  502.         -- if we are allowed to move at both directions - just do it!
  503.         if (destination[coordinateFirst]-location[coordinateFirst]) * directionFirst >= 0
  504.             and (destination[coordinateSecond]-location[coordinateSecond]) * directionSecond >= 0 then
  505.             -- BTW, we just check there that coordinate difference and destination has the same sign
  506.             -- Otherwise turtle that is already went to "second" coordinate won't be able to change it's "first" coordinate
  507.             -- Then just use gotoOne to go to the desired location
  508.             gotoOne (coordinateFirst, destination[coordinateFirst])            
  509.             gotoOne (coordinateSecond, destination[coordinateSecond])            
  510.         else
  511.             -- If we are not allowed to move by any of those coordinates in current zone
  512.             -- Just head up to the second zone
  513.             local nextPosition = naviData[coordinateSecond]
  514.             -- We need to do that for actually leave z1 and z4 since they are one block bigger
  515.             if zone == "z4" or zone == "z1" then
  516.                 nextPosition = nextPosition + 1
  517.             end
  518.             -- go to the next zone!                
  519.             gotoOne (coordinateSecond, nextPosition)
  520.         end        
  521.     end
  522.     height(destination.y)
  523.     turnTo(destination.f)
  524. end
  525.  
  526. -- This function is used to actually navigate the turtle. By default it is set to Highway Navigation, but user may set it to other function
  527. -- It's just have to receive a location-like table with 4 coordinates and move turtle.
  528. navigateTo = highwayNavigate
  529.  
  530. function navigationMethod (newMethod)
  531.     assert (type(newMethod) == "function", "Bad navigation method: Function required, got "..type(newMethod), 2)
  532.     navigateTo = newMethod
  533. end
  534.  
  535. --[[
  536. *********************************************************************************************
  537. *                                     Operation part                                        *
  538. *********************************************************************************************
  539. ]]--
  540. -- Fallback location is the point where module goes if it can't get a task from Master
  541. local fallbackLocation = nil
  542. function setFallback (newFallbackLocation)
  543.     fallbackLocation = newFallbackLocation
  544. end
  545.  
  546. -- We need to read all the data we need to move around - turtle's position and navigation zones
  547. -- "initdata" is the file created by Master and containing all the data that's similar for each module placed by that Master
  548. function init ()
  549.     sleep(2)
  550.     local file = fs.open ("/disk/comminitdata", "r")
  551.     local posFile = fs.open ("/disk/posdata", "r")
  552.     local naviFile = fs.open ("/disk/navidata", "r")
  553.     local communicationData = textutils.unserialize (file.readAll ())
  554.     Master = communicationData.MasterID
  555.     channel = communicationData.channel
  556.     -- set module's location
  557.     location = textutils.unserialize (posFile.readAll ())
  558.     -- set navigation data
  559.     naviData = textutils.unserialize (naviFile.readAll ())
  560.  
  561.     -- Then send a request to Master, to get our ID and to let Master remember us in its state table for modules
  562.     local response = request ("Master", 5)
  563.     ID = response.NewID
  564. end
  565.  
  566. -- Here is the task table. It is the table, that contains all the task module can get form Master and associated functions
  567. -- The table should be filled by user of this API ^_~
  568. -- Module operation is
  569. --  1) Requesting a task from master
  570. --  2) Moving to the location specified in response (if present)
  571. --  3) Executing the associated function
  572. -- There is always a default task "return" which returns module to Master.
  573. -- response from Master is always passed to the function, so, if it contains additional data, you can use it
  574. -- Return is a task to return. Master should pass a set of coordinates as well as "f" direction to make module face the Master.
  575. tTasks = {
  576.     Return = function (response)
  577.         move ("forward")
  578.         dumpStuff ()
  579.         request ("Returned", 3)
  580.         sleep (30)
  581.     end
  582. }
  583.  
  584. -- Function to add tasks to the task table
  585. function addTasks (taskTable)
  586.     assert (type(taskTable) == "table", "Bad task table. Table required, got "..type(taskTable), 2)
  587.     for key, value in pairs (taskTable) do
  588.         assert (type(key) == "string", "Bad task. String required, got "..type(key), 2)
  589.         assert (type(value) == "function", "Bad task function. Function required, got "..type(value), 2)
  590.         tTasks[key] = value
  591.     end
  592. end
  593.  
  594. -- And one to remove a task ^_^
  595. function rmTask (task)
  596.     assert (type(task) == "string", "Bad task. String required, got "..type(task), 2)
  597.     tTasks [task] = nil
  598. end
  599.  
  600. -- And a main operation function
  601. function operate ()
  602.     move ("forward")
  603.     while true do
  604.         local task
  605.         -- failedRequests indicates how many times Master didn't answered to request
  606.         local failedRequests = 0
  607.         while task == nil do
  608.             task = request ("Task", 5)
  609.             if task == nil then
  610.                 failedRequests = failedRequests + 1
  611.                 -- if there are 6 requests failed, and fallbackLocation is set then change position to fallback position
  612.                 if failedRequests >= 6 and fallbackLocation ~= nil then
  613.                     print "No response from Master after 6 attempts. Moving to fallback position..."
  614.                     navigateTo (fallbackLocation)
  615.                 end
  616.             end
  617.         end
  618.         if task.x ~= nil and task.z ~= nil then
  619.             navigateTo (task)
  620.         end
  621.         tTasks [task.Task](task) -- Task. tttTask. Tasktask. taskataskatask. HerpDerp.
  622.     end
  623. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement