View difference between Paste ID: WdqW9G5m and L6ZMPRfZ
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