UNOBTANIUM

ComputerCraft Furnace Turtle

Jun 17th, 2015
326
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.60 KB | None | 0 0
  1. local system = "my furnace";
  2. rednet.open("left");
  3. local pos = {["x"]=0, ["y"]=0, ["z"]=0, ["r"]=1};
  4.  
  5. local currentTask = {["taskname"]="idle"};
  6. local slot = {};
  7. for i = 1, 16, 1 do
  8.     table.insert(slot, {["state"]="empty"});
  9. end
  10.  
  11.  
  12. -- MOVEMENT
  13.  
  14. function savePos()
  15.     local file = fs.open("furnacestation","w");
  16.         file.writeLine(string.gsub(textutils.serialize(pos),"\n%S-",""));
  17.         file.writeLine(string.gsub(textutils.serialize(currentTask),"\n%S-",""));
  18.         file.writeLine(string.gsub(textutils.serialize(slot),"\n%S-",""));
  19.         file.writeLine(system);
  20.     file.close();
  21.     writeTask();
  22. end
  23.  
  24. function load()
  25.     if not fs.exists("furnacestation") then return end
  26.     local file = fs.open("furnacestation","r")
  27.         pos = textutils.unserialize(file.readLine())
  28.         currentTask = textutils.unserialize(file.readLine())
  29.         slot = textutils.unserialize(file.readLine())
  30.         system = file.readLine();
  31.     file.close();
  32. end
  33.  
  34. function turnLeft()
  35.     if (pos.r == 0) then
  36.         pos.r = 3;
  37.     else
  38.         pos.r = pos.r - 1;
  39.     end
  40.     savePos();
  41.     turtle.turnLeft();
  42. end
  43.  
  44. function turnRight()
  45.     pos.r = (pos.r + 1) % 4;
  46.     savePos();
  47.     turtle.turnRight();
  48. end
  49.  
  50. function rotate(r)
  51.     while (not (pos.r == r)) do
  52.         if (r == pos.r-1 or (r == 3 and pos.r == 0)) then
  53.             turnLeft();
  54.         elseif (r == pos.r+1 or (r == 0 and pos.r == 3)) then
  55.             turnRight();
  56.         elseif math.ceil(math.random()) < 0.5 then
  57.             turnLeft()
  58.         else
  59.             turnRight();
  60.         end
  61.     end
  62. end
  63.  
  64. function forward()
  65.     if (pos.r == 0) then
  66.         pos.y = pos.y + 1;
  67.     elseif (pos.r == 1) then
  68.         pos.x = pos.x + 1;
  69.     elseif (pos.r == 2) then
  70.         pos.y = pos.y - 1;
  71.     elseif (pos.r == 3) then
  72.         pos.x = pos.x - 1;
  73.     end
  74.     savePos();
  75.     turtle.forward();
  76. end
  77.  
  78. function up()
  79.     pos.z = pos.z + 1;
  80.     savePos();
  81.     turtle.up();
  82. end
  83.  
  84. function down()
  85.     pos.z = pos.z - 1;
  86.     savePos();
  87.     turtle.down();
  88. end
  89.  
  90. function moveTo(x,y,z)
  91.     while (not (x == pos.x and y == pos.y and z == pos.z)) do
  92.  
  93.         if (pos.y == 0 and not (z == pos.z) and pos.x > 0) then
  94.             while (z > pos.z) do
  95.                 if (turtle.detectUp()) then
  96.                     moveTo(0, 0, pos.z);
  97.                 end
  98.                 up();
  99.             end
  100.             while (z < pos.z) do
  101.                 if (turtle.detectDown()) then
  102.                     moveTo(0, 0, pos.z);
  103.                 end
  104.                 down();
  105.             end
  106.         elseif (not (pos.y == y) and pos.x > 0) then
  107.             if (pos.y < y) then
  108.                 rotate(0);
  109.                 forward();
  110.             elseif (pos.y > y) then
  111.                 rotate(2);
  112.                 forward();
  113.             end
  114.         elseif (not (pos.x == x)) then
  115.             if (pos.x < x) then
  116.                 rotate(1);
  117.                 forward();
  118.             elseif (pos.x > x) then
  119.                 rotate(3);
  120.                 forward();
  121.             end
  122.         elseif (not (pos.z == z)) then
  123.             if (pos.y == -1) then
  124.                 rotate(0);
  125.                 forward();
  126.             elseif (pos.y == 1) then
  127.                 rotate(2);
  128.                 forward();
  129.             end
  130.         end
  131.     end
  132. end
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139. -- INVENTORY
  140.  
  141. function countSlots(type)
  142.     local count = 0;
  143.     for i = 1, 16, 1 do
  144.         if (slot[i].state == type) then
  145.             count = count + 1;
  146.         end
  147.     end
  148.     return count;
  149. end
  150.  
  151. function findSlots(type)
  152.     local a = {};
  153.     for i = 1, 16, 1 do
  154.         if (slot[i].state == type) then
  155.             table.insert(a, i);
  156.         end
  157.     end
  158.     return a;
  159. end
  160.  
  161.  
  162. -- BASE INTERACTIONS
  163.  
  164. function goToBase(askForTask)
  165.     askForTask = askForTask or true
  166.     if (not (pos.x == 0 and pos.y == 0 and pos.z == 0)) then
  167.         moveTo(1,0,0);
  168.         rotate(3);
  169.         forward();
  170.         rotate(1);
  171.     end
  172.     dropAllItems();
  173.     checkFuelReserves();
  174.     refuelTurtle();
  175.     if (askForTask) then
  176.         takeItemsOut();
  177.     end
  178. end
  179.  
  180. function dropAllItems()
  181.     dropItems("finished", "front", "The output chest is full! Please take items out!");
  182.     dropItems("ores", "top", "The input chest is too full! Please take some items out!");
  183.     if (countSlots("fuel") ~= 2) then
  184.         dropItems("fuel", "down", "The fuel chest is too full! Please take some items out!");
  185.     end
  186. end
  187.  
  188. function dropItems(type, direction, error)
  189.     if (countSlots(type) == 0) then
  190.         return;
  191.     end
  192.     if (type == "finished") then
  193.         rotate(2);
  194.     end
  195.     slots = findSlots(type);
  196.     for i, s in pairs(slots) do
  197.         if (turtle.getItemCount(s) > 0) then
  198.             turtle.select(s);
  199.             local b = drop(direction);
  200.             if (not b or (b and turtle.getItemCount(s) > 0)) then
  201.                 for i = 1, 10, 1 do
  202.                     drop(direction);
  203.                 end
  204.                 if (turtle.getItemCount(s) > 0) then
  205.                     sendMessage({["state"]="error", ["errormessage"]=error});
  206.                     if (not (type == "finished")) then
  207.                         return;
  208.                     end
  209.                     while (turtle.getItemCount(s) > 0) do
  210.                         os.sleep(15);
  211.                         drop(direction);
  212.                     end
  213.                 end
  214.             end
  215.         end
  216.         slot[s].state = "empty";
  217.         savePos();
  218.     end
  219.     if (type == "finished") then
  220.         rotate(1);
  221.     end
  222. end
  223.  
  224. function drop(direction)
  225.     if (direction == "front") then
  226.         return turtle.drop();
  227.     elseif (direction == "down") then
  228.         return turtle.dropDown();
  229.     elseif (direction == "up") then
  230.         return turtle.dropUp();
  231.     end
  232. end
  233.  
  234. function takeItemsOut()
  235.     local emptySlots = findSlots("empty");
  236.     for i, s in pairs(emptySlots) do
  237.         turtle.select(s)
  238.         turtle.suckUp();
  239.         if (turtle.getItemCount(s) == 0) then
  240.             break;
  241.         else
  242.             slot[s].state = "ore";
  243.             savePos();
  244.         end
  245.     end
  246.     if (countSlots("ore") == 0) then
  247.         local delay = os.startTimer(10);
  248.         while (true) do
  249.             local event = { os.pullEvent() };
  250.             if (event[1] == "timer" and event[2] == delay) then
  251.                 break;
  252.             elseif (event[1] == "rednet_message" and event[4] == system and textutils.unserialize(event[3]).taskname == "update") then
  253.                 os.cancelTimer(delay);
  254.                 break;
  255.             elseif (event[1] == "redstone") then
  256.                 break;
  257.             end
  258.         end
  259.         sendMessage({["state"]="idle"});
  260.     else
  261.         sendMessage({["state"]="getemptyfurnace"});
  262.     end
  263. end
  264.  
  265. function refuelTurtle()
  266.     if (turtle.getFuelLevel() < 300) then
  267.         while (true) do
  268.             local fuelSlots = findSlots("fuel");
  269.             if (table.getn(fuelSlots) == 0) then
  270.                 takeFuelOut(1);
  271.                 fuelSlots = findSlots("fuel");
  272.             end
  273.             for i, s in pairs(fuelSlots) do
  274.                 turtle.select(s);
  275.                 while (turtle.getItemCount(s) > 0) do
  276.                     turtle.refuel(1);
  277.                     if (turtle.getFuelLevel() > 2000) then
  278.                         return;
  279.                     end
  280.                 end
  281.             end
  282.             dropItems("fuel", "down", "The fuel chest is too full! Please take some items out!");
  283.             takeFuelOut(2);
  284.         end
  285.     end
  286. end
  287.  
  288. function takeFuelOut(stacks)
  289.     stacks = stacks or 1
  290.     if (stacks > 16) then
  291.         stacks = 16;
  292.     end
  293.     while (true) do
  294.         local emptySlots = findSlots("empty");
  295.         for i = 1, stacks, 1 do
  296.             if (emptySlots[i] == null) then
  297.                 break;
  298.             end
  299.             turtle.select(emptySlots[i]);
  300.             turtle.suckDown();
  301.             if (turtle.getItemCount(emptySlots[i]) > 0) then
  302.                 slot[emptySlots[i]].state = "fuel";
  303.                 savePos();
  304.             end
  305.         end
  306.         local fuelSlots = findSlots("fuel");
  307.         if (table.getn(fuelSlots) == 0) then
  308.             sendMessage({["state"]="error", ["errormessage"]="No fuel left! Please put fuel into the chest!"});
  309.             os.sleep(60);
  310.         else
  311.             return;
  312.         end
  313.     end
  314. end
  315.  
  316. function checkFuelReserves()
  317.     while (true) do
  318.         if (countSlots("fuel") == 2) then
  319.             return;
  320.         end
  321.         dropItems("fuel", "down", "The fuel chest is too full! Please take some items out!");
  322.         takeFuelOut(2);
  323.         if (countSlots("fuel") < 2) then
  324.             local fuelSlots = findSlots("fuel");
  325.             local amount = 0;
  326.             for i, s in pairs(fuelSlots) do
  327.                 amount = turtle.getItemCount(s);
  328.             end
  329.             if (amount >= 128) then
  330.                 return;
  331.             elseif (amount < 32) then
  332.                 sendMessage({["state"]="error", ["errormessage"]="Not enough fuel left! Please put fuel into the chest!"});
  333.                 return;
  334.             else
  335.                 sendMessage({["state"]="error", ["errormessage"]="Low on fuel! Please put fuel into the chest!"});
  336.                 return;
  337.             end
  338.         else
  339.             return;
  340.         end
  341.     end
  342. end
  343.  
  344.  
  345. -- FURNACE INTERACTIONS
  346.  
  347. function writeTask()
  348.     term.clear();
  349.     term.setCursorPos(1, 1);
  350.     print(textutils.serialize(pos));
  351.     print(textutils.serialize(currentTask));
  352. end
  353.  
  354. function doTask()
  355.     while (true) do
  356.         writeTask();
  357.         if (currentTask.taskname == "refuel") then
  358.             refuelFurnace();
  359.         elseif (currentTask.taskname == "retrieveitems") then
  360.             retrieveItem();
  361.         elseif (currentTask.taskname == "additems") then
  362.             addOres();
  363.         elseif (currentTask.taskname == "getemptyfurnace") then
  364.             sendMessage({["state"]="getemptyfurnace"});
  365.             waitForInput();
  366.         elseif (currentTask.taskname == "idle") then
  367.             sendMessage({["state"]="idle"});
  368.             waitForInput();
  369.         end
  370.     end
  371. end
  372.  
  373. function finishedTask()
  374.     sendMessage({["state"] = "update"});
  375.     if (countSlots("ore") == 0) then
  376.         currentTask = {["taskname"]="idle"};
  377.     else
  378.         currentTask = {["taskname"]="getemptyfurnace"};
  379.     end
  380.     savePos();
  381. end
  382.  
  383.  
  384. function refuelFurnace()
  385.     local fuelSlotsCount = countSlots("fuel");
  386.     if (fuelSlotsCount == 0) then
  387.         goToBase(false);
  388.     end
  389.  
  390.     moveTo(currentTask.x, 0, 0);
  391.     if (currentTask.y == 1) then
  392.         rotate(0);
  393.     else
  394.         rotate(2);
  395.     end
  396.     local fuelSlots = findSlots("fuel");
  397.     for i, s in pairs(fuelSlots) do
  398.         local count = turtle.getItemCount(s);
  399.         turtle.select(s);
  400.         turtle.drop();
  401.         if (turtle.getItemCount(s) > 0) then
  402.             break;
  403.         else
  404.             slot[s].state = "empty";
  405.             savePos();
  406.         end
  407.     end
  408.     finishedTask();
  409. end
  410.  
  411. function retrieveItem()
  412.     if (countSlots("empty") == 0) then
  413.         if (countSlots("fuel") + countSlots("finished") == 16) then
  414.             goToBase(false);
  415.         else
  416.             local tempTask = currentTask;
  417.             print("addOres")
  418.             addOres();
  419.             currentTask = tempTask;
  420.         end
  421.     end
  422.     moveTo(currentTask.x, currentTask.y, -1);
  423.     local emptySlots = findSlots("empty");
  424.     s = emptySlots[1];
  425.     turtle.select(s);
  426.     turtle.suckUp();
  427.     if (turtle.getItemCount(s) == currentTask.itemcount) then
  428.         slot[s].state = "finished";
  429.     elseif (turtle.getItemCount(s) == 0) then
  430.         --moveTo(currentTask.x, currentTask.y, 1);
  431.         slot[s].state = "finished";
  432.         turtle.suckDown();
  433.     else
  434.         slot[s].state = "finished";
  435.         while (turtle.getItemCount(s) ~= currentTask.itemcount) do
  436.             os.sleep(10);
  437.             turtle.suckUp();
  438.         end
  439.     end
  440.     savePos();
  441.     finishedTask();
  442. end
  443.  
  444. function addOres() -- can be improved for fuel efficiency
  445.     moveTo(currentTask.x, currentTask.y, 1);
  446.     local oreSlots = findSlots("ore");
  447.     local s = oreSlots[1];
  448.     local count = turtle.getItemCount(s);
  449.     turtle.select(s);
  450.     turtle.dropDown();
  451.     if (turtle.getItemCount(s) == 0) then
  452.         slot[s].state = "empty";
  453.         sendMessage({["state"]="setfurnace", ["furnacenumber"]=currentTask.furnacenumber, ["itemcount"]=count});
  454.     elseif (count-turtle.getItemCount(s) == 0) then
  455.         slot[s].state = "finished";
  456.     end
  457.     savePos();
  458.     finishedTask();
  459. end
  460.  
  461.  
  462. -- MESSAGES
  463.  
  464. function sendMessage(message)
  465.     rednet.broadcast(textutils.serialize(message), system);
  466. end
  467.  
  468.  
  469. function waitForInput()
  470.     while (true) do
  471.         writeTask();
  472.         local e = { os.pullEvent() }
  473.         if (e[1] == "rednet_message" and e[4] == system) then
  474.             message = textutils.unserialize(e[3]);
  475.             if (type(message) == "table") then
  476.                 if (message["taskname"] == "refuel" or message["taskname"] == "retrieveitems" or message["taskname"] == "additems") then
  477.                     currentTask = message;
  478.                     return; -- to doTask()
  479.                 elseif (message["taskname"] == "checkitems") then
  480.                     currentTask = {["taskname"]="idle"};
  481.                     goToBase(); -- may break stuff when ore items got picked up allready? -- sends message, requires response
  482.                 elseif (message["taskname"] == "noemptyfurnace") then
  483.                     currentTask = {["taskname"]="idle"};
  484.                     takeItemsOut(); -- sends message, requires response
  485.                 end
  486.             end
  487.         end
  488.     end
  489. end
  490.  
  491. load();
  492. doTask();
Advertisement
Add Comment
Please, Sign In to add comment