I’m doing a fair bit of mucking about in Minecraft lately, specifically with All The Mods 3 Remix. One thing that’s a common problem in modded minecraft is maintaining stock of materials.
A common solution when using Applied Energistics 2 is to leverage ME Level Emitters to shut off autocrafters when you reach a specified stock level. Another solution is to simply ram all your autocrafted products into limited storage units (like Storage Drawers) so that they back up and can’t produce any more.
Both of these have some problems. Level Emitters burn AE2 channels, are complex, and take up significant space. Storage Drawers can lead to tick lag when machines are backed up trying to unload contents, and is not suitable for all cases.
Enter OpenComputers. OC lets you set up computers in Minecraft which can do quite a lot of stuff. In this case, I’m using it for automated stock management.
OpenComputers Setup
You’ll need an OC Computer with all its relevant subcomponents set up, which is beyond the scope of this discussion. You shouldn’t require any high tier components, but you will require a network card at minimum. You will also require an Adapter, to link up to your AE2 network and a Redstone I/O block (if you want your system to turn something on/off).
Place the Adapter against any part of your AE2 network, and it should link up. I’ve put mine against a ME Controller. Place the Redstone I/O in a position where it can turn on your production system (by turning OFF the redstone signal).
Production Setup
I’ve written this with an Environmental Tech Void Ore Miner in mind. In this setup, ore from the miner is random and you must take all ore in order for other ore to be produced. All ore from the Miner goes into Industrial Foregoing Black Hole Units.
From there, there are regular AE2 recipe patterns to process the ore on demand. These go through a fairly complex Mekanism ore processing setup, but that’s out of scope for this.
Your Adapter should be connected to an AE2 network that can see the products of the production and the recipes themselves.
Stock Management Script
Following is the actual autocrafter script. Put this and the stock list into an OpenComputers computer and run it.
It will check your stock levels at the defined intervals. If anything was crafted, it will poll every few seconds until those crafting jobs are completed, then check levels against after a shorter period. The longer period is used when stock levels are full.
-- Stock Management Script
-- Adapted from https://oc.cil.li/topic/1426-ae2-level-auto-crafting/
local component = require("component")
local gpu = component.gpu
-- Import the stocklist
require("stocklist")
results = {} -- Array that holds currently pending crafts
while true do
needOres = false
loopDelay = maxDelay
-- Process crafting indexes
for curIdx = 1, #items do
curName = items[curIdx][1]
curDamage = items[curIdx][2]
curMinValue = items[curIdx][3]
curMaxRequest = items[curIdx][4]
-- io.write("Checking for " .. curMinValue .. " of " .. curName .. "\n")
storedItem = meController.getItemsInNetwork({
name = curName,
damage = curDamage
})
-- Write status of item
io.write("Network contains ")
gpu.setForeground(0xCC24C0) -- Purple-ish
io.write(storedItem[1].size)
gpu.setForeground(0xFFFFFF) -- White
io.write(" items with label ")
gpu.setForeground(0x00FF00) -- Green
io.write(storedItem[1].label .. "\n")
gpu.setForeground(0xFFFFFF) -- White
-- We need to craft some of this item
if storedItem[1].size < curMinValue then
delta = curMinValue - storedItem[1].size
craftAmount = delta
if delta > curMaxRequest then
craftAmount = curMaxRequest
end
-- Write out status message
io.write(" Need to craft ")
gpu.setForeground(0xFF0000) -- Red
io.write(delta)
gpu.setForeground(0xFFFFFF) -- White
io.write(", requesting ")
gpu.setForeground(0xCC24C0) -- Purple-ish
io.write(craftAmount .. "... ")
gpu.setForeground(0xFFFFFF) -- White
-- Retrieve a craftable recipe for this item
craftables = meController.getCraftables({
name = curName,
damage = curDamage
})
if craftables.n >= 1 then
-- Request some of these items
cItem = craftables[1]
retval = cItem.request(craftAmount)
gpu.setForeground(0x00FF00) -- Green
io.write("OK\n")
gpu.setForeground(0xFFFFFF) -- White
-- Flag that we made something, so turn back on the inputs
table.insert(results,retval)
needOres = true
else
-- Could not find a craftable for this item
gpu.setForeground(0xFF0000) -- Red
io.write(" Unable to locate craftable for " .. storedItem[1].name .. "\n")
gpu.setForeground(0xFFFFFF) -- White
end
end
end
if needOres == true then
-- We crafted stuff. Turn off redstone and set a short delay
if redstoneControl ~= nil then
io.write("Setting redstone controller to 0.\n")
redstoneControl.setOutput(redstoneControlSide,0)
end
loopDelay = minDelay
else
-- We didn't. Wait longer.
if redstoneControl ~= nil then
io.write("Setting redstone controller to 15..\n")
redstoneControl.setOutput(redstoneControlSide,15)
end
loopDelay = maxDelay
end
-- Wait for pending crafts to be done
while #results > 0 do
-- See if we can complete a craft
for curIdx = 1, #results do
curCraft = results[curIdx]
if curCraft.isCanceled() or curCraft.isDone() then
io.write("A craft was completed.\n")
table.remove(results,curIdx)
break
else
-- A short delay if we are waiting for crafts to finish
io.write("A craft is pending, sleeping for 5 seconds...\n")
os.sleep(5)
end
end
end
io.write("Sleeping for " .. loopDelay .. " seconds...\n\n")
os.sleep(loopDelay)
end
Stock List
This should be called stocklist.lua
and placed in the same directory as the autocrafter. This defines settings and the list of stock. Set redstoneControl
and redstoneControlSide
to nil
if you aren’t using that feature.
You should set the stock craft size to something that is a fraction of the stock wanted figure, because it’s quite likely to craft an extra block. Don’t set it to 1 or something, otherwise the system will burn a lot of crafting cpus and run poorly.
Each entry is composed of the itemid for the item, “damage”, the number you want to keep in stock, and the max number to try and craft at once. Damage in this context is a subid which is used by a lot of mods to differentiate between items without burning a lot of item ids. You can see some examples below.
local component = require("component")
-- Set these to the relevant components or nil if missing
meController = component.proxy(component.me_controller.address)
redstoneControl = component.proxy(component.redstone.address)
redstoneControlSide = sides.up
-- Each element of the array is "item", "damage", "number wanted", "max craft size"
-- Damage value should be zero for base items
items = {
{ "tconstruct:ingots", 0, 16384, 1024 }, -- Cobalt Ingot
{ "tconstruct:ingots", 1, 16384, 1024 }, -- Ardite Ingot
{ "thermalfoundation:material", 128, 16384, 1024 }, -- Copper Ingot
{ "thermalfoundation:material", 130, 16384, 1024 }, -- Silver Ingot
}
minDelay = 30 -- Seconds between runs if something was crafted
maxDelay = 300 -- Seconds between runs if nothing was crafted
Crafting Recipe Optimization
It helps with performance a lot if you configure your recipes to work in bulk. So, if you have a recipe for Copper Ore to Copper Ingots, instead of doing say;
- 1 Copper Ore –> 3 Copper Ingot
It is much faster in AE2 to set up the recipe as something like;
- 64 Copper Ore –> 3x64 Copper Ingot
That way AE2 can then transfer 64 Copper Ore as a single transfer (and single crafting job) instead of as 64 seperate transfers.