Created
January 9, 2026 21:42
-
-
Save melvyn2/1221acc4db535be7d1cf47fad8c63995 to your computer and use it in GitHub Desktop.
RS2 Autocrafting with CC:T: AdvAE2 Reaction Chamber
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| local next = next | |
| local pairs = pairs | |
| local fsc = peripheral.find("functionalstorage:storage_controller") | |
| local fscn = peripheral.getName(fsc) | |
| local rcs = { peripheral.find("advanced_ae:reaction_chamber") } | |
| local interface = peripheral.find("refinedstorage:interface") | |
| -- Dictionary of name -> (slot, count) | |
| function itemmap (inv) | |
| local items = {} | |
| for s, i in pairs(inv.list()) do | |
| items[i.name] = { slot = s, count = i.count } | |
| end | |
| for s, i in pairs(inv.tanks()) do | |
| items[i.name] = { slot = s, count = i.amount } | |
| end | |
| return items | |
| end | |
| local lava = "minecraft:lava" | |
| local qifluid = "advanced_ae:quantum_infusion_source" | |
| local water = "minecraft:water" | |
| local ccertuscrys = "ae2:charged_certus_quartz_crystal" | |
| local certuscrys = "ae2:certus_quartz_crystal" | |
| local copperingot = "minecraft:copper_ingot" | |
| local crscrys = "appflux:charged_redstone_crystal" | |
| local enderdust = "ae2:ender_dust" | |
| local entrocrys = "extendedae:entro_crystal" | |
| local entrodust = "extendedae:entro_dust" | |
| local entroingot = "extendedae:entro_ingot" | |
| local fluixcrys = "ae2:fluix_crystal" | |
| local fluixdust = "ae2:fluix_dust" | |
| local gsdust = "minecraft:glowstone_dust" | |
| local goldingot = "minecraft:gold_ingot" | |
| local ironingot = "minecraft:iron_ingot" | |
| local lapis = "minecraft:lapis_lazuli" | |
| local matterball = "ae2:matter_ball" | |
| local nstar = "minecraft:nether_star" | |
| local netheriteingot = "minecraft:netherite_ingot" | |
| local osmiumingot = "alltheores:osmium_ingot" | |
| local qalloy = "advanced_ae:quantum_alloy" | |
| local qalloyplate = "advanced_ae:quantum_alloy_plate" | |
| local qidust = "advanced_ae:quantum_infused_dust" | |
| local rsblock = "minecraft:redstone_block" | |
| local rscrys = "appflux:redstone_crystal" | |
| local singularity = "ae2:singularity" | |
| local ssingularity = "advanced_ae:shattered_singularity" | |
| local skydust = "ae2:sky_dust" | |
| local skybingot = "megacells:sky_bronze_ingot" | |
| local skyoingot = "megacells:sky_osmium_ingot" | |
| local skysingot = "megacells:sky_steel_ingot" | |
| local skystone = "ae2:sky_stone_block" | |
| local recipes = { | |
| [ccertuscrys] = { fluid = { name = water, count = 1000 }, items = { [certuscrys] = 64 } }, | |
| [crscrys] = { fluid = { name = water, count = 1000 }, items = { [rscrys] = 64 } }, | |
| [entrocrys] = { fluid = { name = water, count = 500 }, items = { [entrodust] = 32, [fluixcrys] = 32 } }, | |
| [entroingot] = { fluid = { name = water, count = 500 }, items = { [entrodust] = 32, [goldingot] = 32, [lapis] = 32 } }, | |
| [fluixcrys] = { fluid = { name = water, count = 500 }, items = { [ccertuscrys] = 32, [fluixdust] = 32 } }, | |
| [qalloy] = { fluid = { name = qifluid, count = 1000 }, items = { [copperingot] = 4, [ssingularity] = 4, [singularity] = 4 } }, | |
| [qalloyplate] = { fluid = { name = qifluid, count = 1000 }, items = { [qalloy] = 8, [netheriteingot] = 2, [nstar] = 1 } }, | |
| [qifluid] = { fluid = { name = water, count = 4000 }, items = { [qidust] = 1 } }, | |
| [rscrys] = { fluid = { name = water, count = 500 }, items = { [rsblock] = 16, [fluixcrys] = 16, [gsdust] = 16 } }, | |
| [singularity] = { fluid = { name = lava, count = 100 }, items = { [matterball] = 64 } }, | |
| [ssingularity] = { fluid = { name = lava, count = 100 }, items = { [singularity] = 1, [enderdust] = 2, [skydust] = 2 } }, | |
| [skybingot] = { fluid = { name = lava, count = 500 }, items = { [ccertuscrys] = 16, [copperingot] = 16, [skystone] = 16 } }, | |
| [skyoingot] = { fluid = { name = lava, count = 500 }, items = { [ccertuscrys] = 16, [osmiumingot] = 16, [skystone] = 16 } }, | |
| [skysingot] = { fluid = { name = lava, count = 500 }, items = { [ccertuscrys] = 16, [ironingot] = 16, [skystone] = 16 } }, | |
| } | |
| local recipesp = pairs(recipes) | |
| -- Setup function table to parallel pull results | |
| local rcpulls = {} | |
| for _,rc in pairs(rcs) do | |
| local rcn = peripheral.getName(rc) | |
| table.insert(rcpulls, function () | |
| -- Pull out finished items | |
| interface.pullItems(rcn, 10) | |
| -- Max amount is 16B and only quantum infusion can be made | |
| interface.pullFluid(rcn, 16000, qifluid) | |
| end) | |
| end | |
| -- How many of recipe can we make with inv | |
| function recipe_quantity (inv, recipe) | |
| local q = 0 | |
| if inv[recipe.fluid.name] ~= nil then | |
| q = math.floor(inv[recipe.fluid.name].count / recipe.fluid.count) | |
| else | |
| return 0 | |
| end | |
| for n,c in pairs(recipe.items) do | |
| if inv[n] ~= nil then | |
| q = math.min(q, math.floor(inv[n].count / c)) | |
| else | |
| return 0 | |
| end | |
| end | |
| return q | |
| end | |
| while (true) do | |
| -- First pull all outputs | |
| parallel.waitForAll(table.unpack(rcpulls)) | |
| -- Build the map of item -> (slot, quantity) in the functional storage controller | |
| local fsi = itemmap(fsc) | |
| for n,i in recipesp, recipes do | |
| local q = recipe_quantity(fsi, i) | |
| if q > 0 then | |
| print(("Attempting %d of %s"):format(q, n)) | |
| -- Build the table of (attempted) ingredient pulls | |
| local pushes = {} | |
| for _,rc in pairs(rcs) do | |
| -- Only attempt as many runs as is possible, to avoid over-splitting | |
| if q == 0 then | |
| break | |
| else | |
| q = q - 1 | |
| end | |
| -- Move this RC to end, to round-robin distribute attempts | |
| table.insert(rcs, table.remove(rcs, 0)) | |
| table.insert(pushes, function () | |
| local inv = rc.list() | |
| local tanks = rc.tanks() | |
| -- Same issue as below but can safely bail for now (really should retry though TODO) | |
| if inv == nil or tanks == nil then | |
| return | |
| end | |
| -- Only go ahead with the pull if: | |
| -- have 3+ free item slots (slot 6 empty) | |
| -- have 4B free fluid space (leq 12B in input tank) | |
| -- the reactor isn't executing an incompatible recipe (different fluid) | |
| if inv[6] == nil and (tanks[2] == nil or (tanks[2].amount <= 12000 and tanks[2].name == i.fluid.name)) then | |
| -- Retry transfers until they work (https://github.com/cc-tweaked/CC-Tweaked/issues/1817) | |
| local ft = nil | |
| while ft == nil do | |
| ft = rc.pullFluid(fscn, i.fluid.count, i.fluid.name) | |
| end | |
| if ft ~= i.fluid.count then | |
| error(("Only pulled %d of %d %s to %s"):format(ft, i.fluid.count, i.fluid.name, peripheral.getName(rc))) | |
| end | |
| for i,q in pairs(i.items) do | |
| -- Retry here too | |
| local it = nil | |
| while it == nil do | |
| it = rc.pullItems(fscn, fsi[i].slot, q) | |
| end | |
| if it ~= q then | |
| error(("Only pulled %d of %d %s to %s"):format(it, q, i, peripheral.getName(rc))) | |
| end | |
| end | |
| end | |
| end) | |
| end | |
| -- Execute the pull attempts | |
| parallel.waitForAll(table.unpack(pushes)) | |
| -- Rebuild the item map for the remaining ingredients | |
| fsi = itemmap(fsc) | |
| -- Now OK to attempt more recipes without waiting | |
| end | |
| end | |
| end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment