SHOW:
|
|
- or go back to the newest paste.
1 | --[[ | |
2 | Steps: | |
3 | 1. Build a Computer and download this script onto your computer (pastebin get) | |
4 | 2. Create a file named "recipes" (without .lua - on my version i had to use "rename recipes.lua recipes") | |
5 | 3. Build a ME Bridge (Mod: Advanced Peripherals) and connect it to your computer | |
6 | 4. Build a Vanilla Minecraft Chest! and connect it to your computer | |
7 | 5. Start the script | |
8 | 6. Insert any (ME System) craftable item into the chest, like 10 Pistons | |
9 | 7. Wait for the recipe beeing registered (Registered recipe: 10x minecraft:piston) | |
10 | 8. You can remove the 10 pistons from the chest | |
11 | 9. If you want to edit the 10, either close the script and edit the recipes file OR just insert 20 pistons into the chest and wait for the computer to edit the recipe | |
12 | ||
13 | Now the computer will always make sure you have 10 pistons in your me system | |
14 | ||
15 | ]] | |
16 | print("Loading autocrafter...") | |
17 | ||
18 | local bridge = peripheral.find("meBridge") | |
19 | local inventory = peripheral.find("minecraft:chest") | |
20 | ||
21 | local maxTaskCount = 4 | |
22 | local maxCoWorker = 1 | |
23 | ||
24 | local recipeList = {} | |
25 | local craftingQueue = {} | |
26 | ||
27 | local function StringSeperate(str, seperator) | |
28 | local words = {} | |
29 | local word = "" | |
30 | ||
31 | if(string.sub(str, str:len(), str:len())~=seperator)then | |
32 | str = str..""..seperator | |
33 | end | |
34 | for x=1,str:len() do | |
35 | local s = string.sub(str,x,x) | |
36 | if(s==seperator)then | |
37 | table.insert(words, word) | |
38 | word = "" | |
39 | else | |
40 | word = word..s | |
41 | end | |
42 | end | |
43 | return words | |
44 | end | |
45 | ||
46 | local f = io.open("recipes", ab) | |
47 | ||
48 | for line in io.lines("recipes")do | |
49 | local tab = StringSeperate(line, "|") | |
50 | if(tab[1]~=nil)and(tab[2]~=nil)and(tab[3]~=nil)and(tab[4]~=nil)and(tab[5]~=nil)then | |
51 | print("Registered recipe: "..tab[3].."x "..tab[1]..":"..tab[2]) | |
52 | os.sleep(0.2) | |
53 | local recipe = {name=tab[1],damage=tonumber(tab[2]),minAmount=tonumber(tab[3]),maxCraftAmount=tonumber(tab[4]),fails=0,timer=0} | |
54 | if(tab[5]=="true")then | |
55 | recipe.useDmg=true | |
56 | else | |
57 | recipe.useDmg=false | |
58 | end | |
59 | table.insert(recipeList, recipe) | |
60 | end | |
61 | end | |
62 | f:close() | |
63 | ||
64 | function SaveToFile() | |
65 | local file = io.open("recipes", "wb") | |
66 | for k,v in pairs(recipeList)do | |
67 | if(v.useDmg)then | |
68 | file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|true|", "\n") | |
69 | else | |
70 | file.write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|false|", "\n") | |
71 | end | |
72 | end | |
73 | file:close() | |
74 | end | |
75 | ||
76 | local function GetActiveTaskCount() | |
77 | local n = 0 | |
78 | for k,v in pairs(bridge.getCraftingCPUs())do | |
79 | if(type(v)=="table")then | |
80 | if(v.isBusy==true)then | |
81 | n = n+1 | |
82 | end | |
83 | end | |
84 | end | |
85 | return n | |
86 | end | |
87 | ||
88 | local function GetAvailableCpuCount() | |
89 | return #bridge.getCraftingCPUs() - GetActiveTaskCount() | |
90 | end | |
91 | ||
92 | local function GetRecipe(pattern) | |
93 | for k,v in pairs(recipeList)do | |
94 | if(v.name==pattern.name)then | |
95 | if(pattern.damage==nil)then | |
96 | return v | |
97 | end | |
98 | if(v.useDmg)then | |
99 | if(v.damage==pattern.damage)then | |
100 | return v | |
101 | end | |
102 | else | |
103 | return v | |
104 | end | |
105 | end | |
106 | end | |
107 | return nil | |
108 | end | |
109 | ||
110 | local function GetStoredItemAmountNetwork(recipe) | |
111 | return bridge.getItem(recipe).count | |
112 | end | |
113 | ||
114 | local function GetAmount(itemAmount, recipe) | |
115 | local amount = 0 | |
116 | if(itemAmount < recipe.minAmount)then | |
117 | if(recipe.maxCraftAmount > 0)then | |
118 | if(recipe.minAmount-itemAmount > recipe.maxCraftAmount)then | |
119 | amount = recipe.maxCraftAmount | |
120 | else | |
121 | amount = recipe.minAmount-itemAmount | |
122 | end | |
123 | else | |
124 | amount = recipe.minAmount-itemAmount | |
125 | end | |
126 | end | |
127 | return amount | |
128 | end | |
129 | ||
130 | function GetRecipeKey(pattern) | |
131 | for k,v in pairs(recipeList)do | |
132 | if(v.name == pattern.name)then | |
133 | if(pattern.damage==nil)then return k end | |
134 | if(v.useDmg)then | |
135 | if(v.damage == pattern.damage)then | |
136 | return k | |
137 | end | |
138 | else | |
139 | return k | |
140 | end | |
141 | end | |
142 | end | |
143 | return nil | |
144 | end | |
145 | ||
146 | local function CheckCraftingRecipe(pattern) | |
147 | local recipe = GetRecipe(pattern) | |
148 | local item = {item=pattern} | |
149 | if(recipe~=nil)then | |
150 | local storedAmount = pattern.count | |
151 | local neededItemAmount = GetAmount(storedAmount, recipe) | |
152 | if(neededItemAmount > 0)then | |
153 | item.count = neededItemAmount | |
154 | table.insert(craftingQueue, item) | |
155 | return true | |
156 | end | |
157 | end | |
158 | return false | |
159 | end | |
160 | ||
161 | local function CheckAllRecipes() | |
162 | for k,v in pairs(bridge.listCraftableItems())do | |
163 | if(type(v)=="table")then | |
164 | CheckCraftingRecipe(v) | |
165 | end | |
166 | end | |
167 | end | |
168 | ||
169 | function RemoveRecipe(item) | |
170 | local key = -1 | |
171 | for k,v in pairs(recipeList)do | |
172 | if(v.name == item.name)and(v.damage== item.damage)then | |
173 | key = k | |
174 | end | |
175 | end | |
176 | if(key>=0)then | |
177 | table.remove(recipeList, key) | |
178 | end | |
179 | SaveToFile() | |
180 | end | |
181 | ||
182 | local function GetCraftable(item) | |
183 | for k,v in pairs(bridge.listCraftableItems())do | |
184 | if(item.useDmg)then | |
185 | if(bridge.getItem(v).name==item.name)then | |
186 | if(item.useDmg)then | |
187 | if(v.damage==item.damage)then | |
188 | return v | |
189 | end | |
190 | end | |
191 | return v | |
192 | end | |
193 | end | |
194 | end | |
195 | end | |
196 | ||
197 | local function FindKeyInTable(table, item) | |
198 | for k,v in pairs(table)do | |
199 | if(v==item)then | |
200 | return k | |
201 | end | |
202 | end | |
203 | return nil | |
204 | end | |
205 | ||
206 | local function isItemCrafting(itemState) | |
207 | local meItem = bridge.getItem({name=itemState.item.name}) | |
208 | if(meItem.amount > 0)then | |
209 | return bridge.isItemCrafting(meItem) | |
210 | else | |
211 | print(meItem.amount.." "..itemState.curAmount + itemState.amountToCraft) | |
212 | return (meItem.count < itemState.curAmount + itemState.amountToCraft) | |
213 | end | |
214 | end | |
215 | ||
216 | local function UpdateCraftingQueue() | |
217 | while(#craftingQueue > 0)do | |
218 | local activeCoWorkers = {} | |
219 | local craftingQueuesToRemove = {} | |
220 | for k,v in pairs(craftingQueue)do | |
221 | if(#activeCoWorkers+1 <= maxCoWorker)then | |
222 | local stack = v.item | |
223 | local recipeKey = GetRecipeKey(stack) | |
224 | ||
225 | local waittimer = 0 | |
226 | local multiplier = 1 | |
227 | ||
228 | if(recipeList[recipeKey].fails > 0)and(recipeList[recipeKey].fails <=10)then | |
229 | multiplier = recipeList[recipeKey].fails | |
230 | elseif(recipeList[recipeKey].fails > 10)then | |
231 | multiplier = 20 | |
232 | end | |
233 | waittimer = multiplier * 30 | |
234 | if(os.clock()>=recipeList[recipeKey].timer+waittimer)then | |
235 | if not(bridge.isItemCrafting({name=stack.name, count=v.count}))then | |
236 | local currentItemState = {item=stack, curAmount = stack.count, amountToCraft = v.count} | |
237 | local task, errormsg = bridge.craftItem({name=stack.name, count=v.count}) | |
238 | if(task~=nil)then | |
239 | print("Scheduled Task: "..v.count.." ("..stack.name..") "..stack.displayName) | |
240 | table.insert(activeCoWorkers, currentItemState) | |
241 | recipeList[recipeKey].fails = 0 | |
242 | else | |
243 | print("------------------") | |
244 | print("Error scheduling task: "..v.count.." ("..stack.name..") "..stack.displayName) | |
245 | print(errormsg) | |
246 | print("------------------") | |
247 | recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1 | |
248 | recipeList[recipeKey].timer = os.clock() | |
249 | end | |
250 | end | |
251 | end | |
252 | table.insert(craftingQueuesToRemove, v) | |
253 | end | |
254 | end | |
255 | ||
256 | if(#craftingQueuesToRemove > 0)then | |
257 | for k,v in pairs(craftingQueuesToRemove)do | |
258 | local id = FindKeyInTable(craftingQueue, v) | |
259 | table.remove(craftingQueue, id) | |
260 | end | |
261 | end | |
262 | ||
263 | while(#activeCoWorkers > 0)do | |
264 | local finishedCoworker = {} | |
265 | for k,v in pairs(activeCoWorkers)do | |
266 | if not(bridge.isItemCrafting({name=v.item.name, count=v.amountToCraft}))then | |
267 | print("Task done: "..v.amountToCraft.." ("..v.item.name..") "..v.item.displayName) | |
268 | table.insert(finishedCoworker, v) | |
269 | end | |
270 | end | |
271 | if(#finishedCoworker>0)then | |
272 | for k,v in pairs(finishedCoworker)do | |
273 | local id = FindKeyInTable(activeCoWorkers, v) | |
274 | table.remove(activeCoWorkers, id) | |
275 | end | |
276 | end | |
277 | os.sleep(0.75) | |
278 | end | |
279 | os.sleep(0.75) | |
280 | end | |
281 | end | |
282 | ||
283 | function FindKeyWithItemName(table, itemname, damage) | |
284 | for k,v in pairs(table)do | |
285 | if(v.name==itemname)and(v.damage == damage)then | |
286 | return k | |
287 | end | |
288 | end | |
289 | return nil | |
290 | end | |
291 | ||
292 | local function CheckChestForNewEntrys() | |
293 | local items = {} | |
294 | local itemAmounts = {} | |
295 | local somethingChanged = false | |
296 | ||
297 | if(inventory~=nil)then | |
298 | for x=1,inventory.size(), 1 do | |
299 | local item = inventory.getItemDetail(x) | |
300 | if(item~=nil)then | |
301 | if(item.damage==nil)then item.damage = 0 end | |
302 | table.insert(items, item) | |
303 | end | |
304 | end | |
305 | os.sleep(0.5) | |
306 | end | |
307 | os.sleep(1) | |
308 | ||
309 | if(#items > 0)then | |
310 | for k,v in pairs(items)do | |
311 | local key = FindKeyWithItemName(itemAmounts, v.name, v.damage) | |
312 | if(key~=nil)then | |
313 | itemAmounts[key].count = itemAmounts[key].count + v.count | |
314 | else | |
315 | table.insert( itemAmounts, {name=v.name, damage=v.damage, count = v.count}) | |
316 | end | |
317 | ||
318 | end | |
319 | end | |
320 | ||
321 | if(#itemAmounts > 0)then | |
322 | for k,v in pairs(itemAmounts)do | |
323 | local key = FindKeyWithItemName(recipeList, v.name, v.damage) | |
324 | if(key~=nil)then | |
325 | if(recipeList[key].minAmount ~= v.count)then | |
326 | print("Edited recipe: "..v.name.. ":"..v.damage.." new count: "..v.count) | |
327 | end | |
328 | somethingChanged = true | |
329 | recipeList[key].minAmount = v.count | |
330 | else | |
331 | table.insert( recipeList, {name=v.name, damage=v.damage, minAmount = v.count, maxCraftAmount = 0, useDmg = true, fails = 0, timer = 0}) | |
332 | somethingChanged = true | |
333 | print("Registered recipe: "..v.count.."x "..v.name.. ":"..v.damage) | |
334 | end | |
335 | end | |
336 | if(somethingChanged)then | |
337 | SaveToFile() | |
338 | end | |
339 | end | |
340 | end | |
341 | ||
342 | print("Autocrafter successfully loaded!") | |
343 | ||
344 | while true do | |
345 | CheckChestForNewEntrys() | |
346 | os.sleep(1) | |
347 | if(GetActiveTaskCount()<maxTaskCount)then | |
348 | CheckAllRecipes() | |
349 | os.sleep(1) | |
350 | UpdateCraftingQueue() | |
351 | --if not(pcall(UpdateCraftingQueue))then | |
352 | -- print("Autocrafter got an unexpected error") | |
353 | --end | |
354 | else | |
355 | os.sleep(5) | |
356 | end | |
357 | os.sleep(1) | |
358 | end |