View difference between Paste ID: HUnzXZjm and xsWFjPyy
SHOW: | | - or go back to the newest paste.
1
--[[
2
Copyright (c) 2019, David Moore
3
All rights reserved.
4
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are met:
7
8
1. Redistributions of source code must retain the above copyright notice, this
9
   list of conditions and the following disclaimer.
10
2. Redistributions in binary form must reproduce the above copyright notice,
11
   this list of conditions and the following disclaimer in the documentation
12
   and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25
The views and conclusions contained in the software and documentation are those
26
of the authors and should not be interpreted as representing official policies,
27
either expressed or implied, of the <project name> project.
28
]]
29
30
-- Ladies and gentlemen, my killbot has Lotus Notes and a machine gun. It is the finest available.
31
32
-- turn this on to enable debug logging
33
logging = false
34
-- where to write the things
35
logfile = "/autocrafter9000.log"
36
37
-- chest on the left of the computer, ME interface on the right
38
chest = peripheral.wrap("left")
39
interface = peripheral.wrap("right")
40
41
-- time to sleep between checks
42
sleepSeconds = 3
43
44
-- how frequently, in seconds, to print an error if something cannot be crafted
45
-- due to missing components
46
warningFreq = 120
47
48
function logEvent(str)
49
 if logging then
50
  f = fs.open(logfile, "a")
51
  f.writeLine(str)
52
  f.close()
53
  print(str)
54
 end
55
end
56
57
function newItemHolder(name,dmg,count,job)
58
 t = {}
59
 t["name"] = name
60
 t["dmg"] = 0 + dmg
61
 t["count"] = 0 + count
62
 t["job"] = job
63
 t["key"] = name .. "@" .. dmg
64
 return t
65
end
66
67
itemsPersistent = {}
68
warnedItemTimes = {}
69
70
-- get list of items in teh chest. This will return an entry for each stack
71
-- so we need to process it further (for items that we want more than 64 of)
72
while true do
73
 chestList = chest.list()
74
 chestTotals = {}
75
 for k,v in pairs(chestList) do
76
  theItem = newItemHolder(v.name,v.damage,v.count,nil)
77
  logEvent("Got chest stack " .. theItem["name"] .. "@" .. theItem["dmg"] .. " qty " .. theItem["count"])
78
  -- we need to add the stacks together to get real totals
79
  if chestTotals[theItem["key"]] then
80
   chestTotals[theItem["key"]] = chestTotals[theItem["key"]] + theItem["count"]
81
  else
82
   chestTotals[theItem["key"]] = theItem["count"]
83
  end
84
  -- if our persistent item store (which contains in-progress crafting jobs) does not have this item, then add it
85
  -- the only way we can prevent multiple redundant crafting jobs, that i have found, is to save the job object
86
  -- and check if it is still in progress. I haven't found a way to interrogate the interface for jobs in-progress
87
  if not itemsPersistent[theItem["key"]] then
88
   itemsPersistent[theItem["key"]] = theItem
89
  end
90
 end
91
92
 for chestItemName,chestItemCount in pairs(chestTotals) do
93
  craftOkay = false
94
  logEvent("After chest item processing, got chest item " .. chestItemName .. " qty " .. chestItemCount)
95
  networkItemSearchResult = interface.findItems(chestItemName)
96
  --logEvent(networkItemSearchResult)
97
  if networkItemSearchResult[1] then
98
   metadata = networkItemSearchResult[1].getMetadata()
99
   networkItemCount = metadata.count
100
   logEvent("Got network item " .. chestItemName .. " qty " .. networkItemCount)
101
   
102
   -- if there is less in the network on the right than in the chest on the left
103
   if networkItemCount < chestItemCount then
104
    diff = chestItemCount - networkItemCount
105
    
106
    -- check if we have a crafting job stored for this item, and whether it's finished
107
    if itemsPersistent[chestItemName]["job"] then
108
     if itemsPersistent[chestItemName]["job"].isFinished() then
109
      okayToCraft = true
110
      itemsPersistent[chestItemName]["job"] = nil
111
     else
112
      okayToCraft = false
113
     end
114
    else
115
     okayToCraft = true
116
    end
117
    
118
    -- check if there is an available CPU
119
    availableCPU = false
120
    cpus = interface.getCraftingCPUs()
121
    for k,v in pairs(cpus) do
122
     if v.busy == false then
123
      availableCPU = true
124
     end
125
    end
126
    
127
    if not availableCPU then
128
     okayToCraft = false
129
     -- print("No CPUs available, skipping")
130
    end     
131
    
132
    if okayToCraft then
133
     -- save the crafting job in the persistent store
134
     itemsPersistent[chestItemName]["job"] = networkItemSearchResult[1].craft(diff)
135
     if itemsPersistent[chestItemName]["job"].status() == "missing" then
136
      if warnedItemTimes[chestItemName] then
137
       if os.clock() - warnedItemTimes[chestItemName] > warningFreq then
138
        okayToPrint = true
139
       else
140
        okayToPrint = false
141
       end
142
      else
143
       okayToPrint = true
144
      end
145
      if okayToPrint then
146
       warnedItemTimes[chestItemName] = os.clock()
147
       print("Missing Components! Cannot craft " .. diff .. " of " .. chestItemName)
148
      end
149
     else
150
      craftOkay = true
151
     end
152
     -- check if the job failed. haven't bothered to test this functionality yet.
153
     -- it should kick in if all CPUs are in use or some such
154
     if not itemsPersistent[chestItemName]["job"] then
155
      print("Could not craft ".. diff .. " of " .. chestItemName)
156
      craftOkay = false
157
     end
158
    else
159
     logEvent("Not crafting " .. chestItemName .. " because of crafting job in progress")
160
     craftOkay = false
161
    end
162
   else
163
    warnedItemTimes[chestItemName] = nil
164
   end
165
  if craftOkay then
166
   warnedItemTimes[chestItemName] = nil
167
   logEvent("Submitted order for " .. diff .. " of " .. chestItemName)
168
   print("Submitted order for " .. diff .. " of " .. chestItemName)
169
  end
170
  end
171
 end
172
 os.sleep(sleepSeconds)
173
end