NanoBob

Computercraft storage server

Jun 21st, 2016
1,013
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.21 KB | None | 0 0
  1. local localChannel=666
  2. local rest={x=156,y=7,z=263}
  3. local drop={x=160,y=6,z=264}
  4.  
  5. local chests={
  6.     {chest=peripheral.wrap("chest_0"),pos={x=1087,y=65,z=381}},
  7.     {chest=peripheral.wrap("chest_1"),pos={x=1087,y=65,z=384}},
  8.     {chest=peripheral.wrap("chest_2"),pos={x=1087,y=65,z=387}},
  9.     {chest=peripheral.wrap("chest_3"),pos={x=1081,y=65,z=381}},
  10.     {chest=peripheral.wrap("chest_4"),pos={x=1081,y=65,z=384}},
  11.     {chest=peripheral.wrap("chest_5"),pos={x=1081,y=65,z=387}},
  12. }
  13.  
  14. local modem=peripheral.wrap("bottom")
  15. local wireless=peripheral.wrap("top")
  16.  
  17.  
  18. if fs.exists("event")==false then shell.run("pastebin get UKPy4iiE event") end
  19. os.loadAPI("event")
  20.  
  21. if fs.exists("utils")==false then shell.run("pastebin get dyvydHtK utils") end
  22. os.loadAPI("utils")
  23.  
  24. if fs.exists("data")==false then shell.run("pastebin get LnvzL7ur data") end
  25. if os.loadAPI("data")==false then error("Failed to load data API") end
  26.  
  27. local taskQue = {}
  28.  
  29. local turtles = {}
  30.  
  31. local craftQue = {}
  32.  
  33.  
  34. local modems={}
  35. modem.open(localChannel)
  36. modems["back"]=modem
  37. modems["wired"]=modem
  38. wireless.open(localChannel)
  39. modems["bottom"]=wireless
  40. modems["wireless"]=wireless
  41.  
  42. local pingLimit = 10
  43. local items={}
  44. local turtleTimer = os.startTimer(10)
  45.  
  46. function indexItems()
  47.     items={}
  48.     for chestID,chest in pairs(chests) do
  49.         for i,stack in pairs(chest.chest.getAllStacks()) do
  50.             local data=stack.all()
  51.             if items[string.lower(data.display_name)]==nil then
  52.                 items[string.lower(data.display_name)]={[chestID]=data.qty}
  53.             else
  54.                 if items[string.lower(data.display_name)][chestID]==nil then
  55.                     items[string.lower(data.display_name)][chestID]=data.qty
  56.                 else
  57.                     items[string.lower(data.display_name)][chestID]=items[string.lower(data.display_name)][chestID]+data.qty
  58.                 end            
  59.             end
  60.         end
  61.     end
  62. end
  63. indexItems()
  64.  
  65. function getItemCount(name)
  66.     local item=items[string.lower(name)]
  67.     if item==nil then return 0 end
  68.     local count=0
  69.     for chestID,itemCount in pairs(item) do
  70.         count=count+itemCount
  71.     end
  72.     return count
  73. end
  74.  
  75. function getItemPosition(name,count)
  76.     local item=items[string.lower(name)]
  77.     if item==nil then return end
  78.     local positions={}
  79.     if count==0 then
  80.         count=1
  81.     end
  82.     local remainder=count
  83.     for chestID,itemCount in pairs(item) do
  84.         remainder=remainder-itemCount
  85.         positions[#positions+1]={pos=chests[chestID].pos,count=itemCount}
  86.         if remainder<=0 then
  87.             return positions
  88.         end
  89.     end
  90.     return positions
  91. end
  92.  
  93. function getIdleTurtle()
  94.     for id,turtle in pairs(turtles) do
  95.         if turtle.status=="idle" then
  96.             return turtle
  97.         end
  98.     end
  99.     return nil
  100. end
  101.  
  102. function statusUpdate(channel,turtle,previous,new)
  103.     --print("Que:\n"..textutils.serialise(taskQue))
  104.     event.handleCCEvents(0.05)
  105.     if new=="idle" then
  106.         turtle.task=nil
  107.         if #taskQue==0 then
  108.             if #craftQue == 0 then return end
  109.             indexItems()
  110.             for i,queEntry in ipairs(craftQue) do
  111.                 if craftItem(queEntry.item,queEntry.count,true) == true then
  112.                     craftItem(queEntry.item,queEntry.count,nil,queEntry.final)
  113.                     craftQue[i]=nil
  114.                     for j=i+1,#craftQue do
  115.                         craftQue[j-i]=craftQue[j]
  116.                     end
  117.                     craftQue[#craftQue]=nil
  118.                     return
  119.                 end
  120.             end
  121.             return
  122.         end
  123.         modems["wireless"].transmit(channel,localChannel,taskQue[1])
  124.         turtle.task=taskQue[1]
  125.         turtle.status="working"
  126.         for id,data in ipairs(taskQue) do
  127.             taskQue[id-1]=data
  128.         end
  129.         taskQue[0]=nil
  130.         taskQue[#taskQue]=nil
  131.     end
  132. end
  133. event.addHandler("onTurtleStatusChange",statusUpdate)
  134.  
  135. function turtleTimed(turtle,channel)
  136.     local command = turtle.task
  137.     if command == nil then return end
  138.     local turtle=getIdleTurtle()
  139.     if turtle==nil then
  140.         taskQue[#taskQue+1]=command
  141.     else
  142.         modems["wireless"].transmit(turtle.channel,localChannel,command)
  143.         turtle.task=command
  144.         turtle.status="working"
  145.     end
  146. end
  147. event.addHandler("onTurtleTimeout",turtleTimed)
  148.  
  149. function createRecipe(targetItem,recipeString)
  150.     data.set(targetItem,recipeString)
  151. end
  152.  
  153. function checkTurtleConnectionTimer(timer)
  154.     if timer ~= turtleTimer then return end
  155.     for channel,turtle in pairs(turtles) do
  156.         if turtle.lastMessage < os.clock() - 20 then
  157.             turtle.missed = turtle.missed + 1
  158.             if turtle.missed > pingLimit then
  159.                 print("Turtle " .. channel .. " has timed out")
  160.                 event.trigger("onTurtleTimeout",turtle,channel)
  161.                 turtles[channel] = nil
  162.                 checkTurtleConnectionTimer(timer)
  163.                 break
  164.             end
  165.         else
  166.             turtle.missed = 0
  167.         end
  168.     end
  169.     --[[
  170.     for channel,turtle in pairs(turtles) do
  171.         if turtle.timer == timer then
  172.             ping(channel)
  173.             if turtle.pingTimer == nil then
  174.                 turtle.missed = 0
  175.                 turtle.pingTimer = os.startTimer(10)
  176.             end
  177.         elseif turtle.pingTimer == timer  and turtle.missed == pingLimit then
  178.             --print("Turtle " .. channel .. " has timed out")
  179.             event.trigger("onTurtleTimeout",turtle,channel)
  180.             turtles[channel] = nil
  181.             return
  182.         elseif turtle.pingTimer == timer and turtle.missed then
  183.             turtle.pingTimer = os.startTimer(10)
  184.             turtle.missed = turtle.missed + 1
  185.         end
  186.     end
  187.     ]]
  188.     turtleTimer = os.startTimer(10)
  189. end
  190. event.addHandler("timer",checkTurtleConnectionTimer)
  191.  
  192. function craftItem(itemName,count,check,final)
  193.     indexItems()
  194.     local hasSubs = false
  195.     local recipe = data.get(itemName,"db/recipes")
  196.     if recipe==nil or recipe=="nil" then return end    
  197.     local command = "craft|"..count.."|"
  198.     if final == nil or final == false then
  199.         command = "innerCraft|"..count.."|"
  200.     end
  201.     print(itemName .." : " .. count)
  202.     for i=1,9 do
  203.         local item = utils.split(recipe,";",i)
  204.         local positions = getItemPosition(item,count)
  205.         local itemFound = false
  206.         if item~=nil and positions ~=nil then
  207.             local remainder=count
  208.             for chestID,data in pairs(positions) do
  209.                 local count=data.count
  210.                 if count>=remainder then
  211.                     command = command .. item ..";".. data.pos.x ..",".. data.pos.y ..",".. data.pos.z .. ";"..i.."|"
  212.                     itemFound = true
  213.                     break
  214.                 end
  215.             end
  216.             if itemFound == false then
  217.                 if data.get(item,"db/recipes")~=nil then
  218.                     if check == nil then
  219.                         craftItem(item,count,nil,false)
  220.                     end
  221.                     hasSubs = true
  222.                 end
  223.             end
  224.         elseif positions == nil and item ~= nil and item ~= ""  then
  225.             print("item not found in system "..tostring(item).." Recipe: "..tostring(not ( data.get(item,"db/recipes") == nil ) ) )
  226.             if data.get(item,"db/recipes")~=nil then
  227.                 if check == nil then
  228.                     craftItem(item,count,nil,false)
  229.                 elseif check ~= false then
  230.                     return false
  231.                 end
  232.                 hasSubs = true
  233.             else
  234.                 print("Not enough items")
  235.             end
  236.         end
  237.     end
  238.    
  239.     if hasSubs == true then
  240.         craftQue[#craftQue+1] = { item = itemName, count = count, final = final }
  241.     end
  242.    
  243.     if check == true and hasSubs == false then
  244.         return true
  245.     elseif check == true then
  246.         return false
  247.     end
  248.     local turtle = getIdleTurtle()
  249.     if turtle==nil then
  250.         craftQue[#craftQue+1] = { item = itemName, count = count, final = final }
  251.         --taskQue[#taskQue+1]=command
  252.     else
  253.         modems["wireless"].transmit(turtle.channel,localChannel,command)
  254.         turtle.task=command
  255.         turtle.status="working"
  256.     end
  257.     print(textutils.serialise(craftQue))
  258. end
  259.  
  260. function ping(channel)
  261.     modems.wireless.transmit(channel,localChannel,"ping")
  262. end
  263.  
  264. local messageHandles={
  265.     ["ping"]=function(replyChannel,message)
  266.         if turtles[replyChannel]==nil then return end
  267.         event.trigger("onPing",replyChannel)
  268.         return "pong"
  269.     end,
  270.    
  271.     ["pong"]=function(replyChannel,message)
  272.         if turtles[replyChannel]==nil then return end
  273.         event.trigger("onPong",replyChannel)
  274.     end,
  275.    
  276.     ["getItemCount"]=function(replyChannel,message)
  277.         indexItems()
  278.         local itemName=utils.split(message,"|",2)
  279.         return "returnItemCount|"..getItemCount(itemName)
  280.     end,
  281.    
  282.     ["requestItemList"]=function(replyChannel,message)
  283.         indexItems()
  284.         local itemString=""
  285.         for itemname,chests in pairs(items) do
  286.             itemString=itemString..itemname..","..getItemCount(itemname)..";"
  287.         end
  288.         return "returnItemList|"..itemString
  289.     end,
  290.    
  291.     ["requestTurtles"]=function(replyChannel,message)
  292.         local turtleString=""
  293.         for channel,turtle in pairs(turtles) do
  294.             turtleString=turtleString..channel..","..turtle.status..","..tostring(turtle.task)..";"
  295.         end
  296.         return "returnTurtles|"..turtleString
  297.     end,
  298.    
  299.     ["requestQue"]=function(replyChannel,message)
  300.         local queString=""
  301.         for _,queCommand in pairs(taskQue) do
  302.             queString=queString..string.gsub(queCommand,"|",";").."|"
  303.         end
  304.         return "returnQue|"..queString
  305.     end,
  306.    
  307.     ["requestItem"]=function(replyChannel,message)
  308.         indexItems()
  309.         local itemName=utils.split(message,"|",2)
  310.         local count=tonumber(utils.split(message,"|",3))
  311.         --print("Item request: "..itemName.."x"..count)
  312.         local positions=getItemPosition(itemName,count)
  313.         local remainder=count
  314.         if positions==nil then return end
  315.         for chestID,data in pairs(positions) do
  316.             ----print(chestID)
  317.             local count=data.count
  318.             if count>remainder then
  319.                 count=remainder
  320.             end
  321.             remainder=remainder-count
  322.             local command="get|"..itemName.."|"..count.."|"..data.pos.x..","..data.pos.y..","..data.pos.z
  323.             --print("Command: "..command)
  324.             local turtle=getIdleTurtle()
  325.             if turtle==nil then
  326.                 taskQue[#taskQue+1]=command
  327.             else
  328.                 modems["wireless"].transmit(turtle.channel,localChannel,command)
  329.                 turtle.task=command
  330.                 turtle.status="working"
  331.             end
  332.             if remainder<=0 then
  333.                 return
  334.             end
  335.         end
  336.     end,
  337.    
  338.     ["addRecipe"]=function(replyChannel,message)
  339.         local item = utils.split(message,"|",2)
  340.         local recipe = utils.split(message,"|",3)
  341.         data.set(item,recipe,"db/recipes")
  342.         --print("Adding recipe: "..recipe)
  343.     end,
  344.    
  345.     ["requestRecipes"]=function(replyChannel,message)
  346.         local returnString = "returnRecipes|"
  347.         for id,_ in pairs(data.getAll("db/recipes")) do
  348.             returnString = returnString .. id .. ";"
  349.         end
  350.         return returnString
  351.     end,
  352.    
  353.     ["requestCraft"]=function(replyChannel,message)
  354.         local itemName=utils.split(message,"|",2)
  355.         local count=tonumber(utils.split(message,"|",3))
  356.         craftItem(itemName,count,nil,true)
  357.     end,
  358.    
  359.     ["getItemPosition"]=function(replyChannel,message)
  360.         indexItems()
  361.         local itemName=utils.split(message,"|",2)
  362.         local posString=""
  363.         local positions=getItemPosition(itemName)
  364.         if positions==nil then return end
  365.         for _,pos in pairs(positions) do
  366.             posString=posString..x..","..y..","..z.."|"
  367.         end
  368.         return posString
  369.     end,
  370.    
  371.     ["sendToTurtles"]=function(replyChannel,message)
  372.         local turtleChannel=utils.split(message,"|",2)
  373.         local message=utils.split(message,"|",3)
  374.         local turtle=turtles[replyChannel]
  375.         turtle.task=message
  376.         turtle.status="working"
  377.        
  378.     end,
  379.    
  380.     ["indexItems"]=function(replyChannel,message)
  381.         indexItems()
  382.         return "confirmed"
  383.     end,
  384.    
  385.     ["assign"]=function(replyChannel)
  386.         if turtles[replyChannel]==nil then
  387.             turtles[replyChannel]={
  388.                 channel=replyChannel,
  389.                 status="idle",
  390.                 lastMessage = os.clock()
  391.             }
  392.             event.trigger("onTurtleAssign",replyChannel,turtles[replyChannel],"confirmed")
  393.             event.trigger("onTurtleStatusChange",replyChannel,turtles[replyChannel],false,"idle")
  394.             return "confirmed"
  395.         else
  396.             event.trigger("onTurtleAssign",replyChannel,turtles[replyChannel],"denied")
  397.             return "denied"
  398.         end
  399.     end,
  400.    
  401.     ["status"]=function(replyChannel,message)
  402.         if turtles[replyChannel]==nil then
  403.             return "denied"
  404.         end
  405.         local previous=turtles[replyChannel].status
  406.         local status=utils.split(message,"|",2)
  407.         turtles[replyChannel].status=status
  408.         event.trigger("onTurtleStatusChange",replyChannel,turtles[replyChannel],previous,status)
  409.     end,
  410.    
  411.     ["requestDropoff"]=function(replyChannel,message)
  412.         return "returnDropoff|"..drop.x..","..drop.y..","..drop.z
  413.     end,
  414.    
  415.     ["requestRestPos"]=function(replyChannel,message)
  416.         return "returnHomePos|"..rest.x..","..rest.y..","..rest.z
  417.     end,
  418. }
  419.  
  420.  
  421. function handleMessages(side,channel,replyChannel,message)
  422.     --print(replyChannel.." : "..message)
  423.     if turtles[replyChannel] ~= nil then
  424.         turtles[replyChannel].lastMessage = os.clock()
  425.     end
  426.     local messageType=utils.split(message,"|",1)
  427.     if messageHandles[messageType]==nil then return end
  428.     local returnMessage=messageHandles[messageType](replyChannel,message)
  429.     event.handleCCEvents(0.10)
  430.     if returnMessage==nil then return end
  431.     --print(replyChannel .. " : " .. returnMessage)
  432.     modems[side].transmit(replyChannel,localChannel,returnMessage)
  433. end
  434. event.addHandler("modem_message",handleMessages)
  435.  
  436. while true do
  437.     event.handleCCEvents()
  438. end
  439.  
  440. print("ENDED GRACEFULLY")
Add Comment
Please, Sign In to add comment