cc-stuff/oregen-manager.lua
Emerson Rosen-Jones e82591297c fix: fix startup logic
Previous: if a KEEP_STOCKED material was between lower and upper, it would
sit there on startup, regardless of whether material was needed in export.

New logic is that materials between the lower and upper bound will try to
export until the lower bound is reached on startup.
2026-01-17 19:02:39 -05:00

359 lines
10 KiB
Lua

-- Manages an oregen facility
local STOCK_TICKER = ""
local EXPORT_STORAGE = ""
local SPEEDOMETER = ""
local CRUSHER_ADDR = "Crusher"
local MELTER_ADDR = "Melter"
local MIXER_ADDR = "Mixer"
local WASHER_ADDR = "Washer"
local SMELTER_ADDR = "Smelter"
local HAUNTER_ADDR = "Haunter"
local PRESS_ADDR = "Press"
local EXPORT_ADDR = "Output"
-- amount to keep in EXPORT_STORAGE
local KEEP_STOCKED = {
["minecraft:iron_nugget"] = 4 * 64,
["minecraft:gold_nugget"] = 4 * 64,
["create:zinc_nugget"] = 4 * 64,
["create:copper_nugget"] = 4 * 64,
["minecraft:netherrack"] = 4 * 64,
["create:cinder_flour"] = 0,
["minecraft:gravel"] = 0,
["minecraft:netherite_scrap"] = 4,
["minecraft:nether_bricks"] = 0,
["oreganized:silver_nugget"] = 4 * 64,
["tfmg:nickel_nugget"] = 4 * 64,
["tfmg:lithium_nugget"] = 64,
["tfmg:bauxite_powder"] = 4 * 64,
["minecraft:flint"] = 0,
["minecraft:andesite"] = 4 * 64,
}
local GLOBAL_LIMS = {
lower = 6 * 64,
upper = 10 * 64,
}
local LIMIT_EXCEPTIONS = {
["create:cinder_flour"] = {
lower = 64,
upper = 2 * 64,
},
["minecraft:gravel"] = {
lower = 10 * 64,
upper = 20 * 64,
},
["minecraft:netherite_scrap"] = {
lower = 0,
upper = 4,
},
["tfmg:lithium_nugget"] = {
lower = -1,
upper = 0,
},
["minecraft:flint"] = {
lower = 64,
upper = 2 * 64,
},
["minecraft:andesite"] = {
lower = 0,
upper = 2 * 64,
},
}
-- if these exist, they will be used up
-- "limit" is the limit on the amt sent at a time (default is 64)
-- "keep" is the amount not to use up (default is 0)
local PRODUCTS = {
{"create:crimsite", CRUSHER_ADDR},
{"create:crushed_raw_iron", MELTER_ADDR},
{"create:crushed_raw_zinc", MELTER_ADDR},
{"create:asurine", CRUSHER_ADDR},
{"create:crushed_raw_copper", MELTER_ADDR},
{"create:veridium", CRUSHER_ADDR, limit = 32},
{"create:ochrum", CRUSHER_ADDR},
{"create:crushed_raw_gold", MELTER_ADDR},
{"minecraft:sand", WASHER_ADDR},
{"minecraft:clay_ball", SMELTER_ADDR},
{"minecraft:brick", HAUNTER_ADDR},
{"minecraft:flint", CRUSHER_ADDR, keep = 4 * 64},
{"minecraft:nether_bricks", CRUSHER_ADDR},
{"minecraft:basalt", CRUSHER_ADDR},
{"create:crushed_raw_silver", WASHER_ADDR, limit = 16},
{"minecraft:calcite", CRUSHER_ADDR},
{"create:crushed_raw_nickel", WASHER_ADDR, limit = 32},
{"tfmg:bauxite", CRUSHER_ADDR},
}
-- these will be crafted when needed
local RECIPES = {
["minecraft:gravel"] = {
ingredients = {
{"minecraft:cobblestone", 2 * 64},
},
addr = CRUSHER_ADDR,
limit = 6,
},
["minecraft:iron_nugget"] = {
ingredients = {
{"minecraft:iron_nugget", 60},
{"minecraft:gravel", 24},
},
addr = PRESS_ADDR,
},
["minecraft:gold_nugget"] = {
ingredients = {
{"minecraft:gold_nugget", 64},
{"minecraft:gravel", 64},
},
addr = PRESS_ADDR,
},
["create:zinc_nugget"] = {
ingredients = {
{"create:zinc_nugget", 64},
{"minecraft:gravel", 32},
},
addr = PRESS_ADDR,
},
["create:copper_nugget"] = {
ingredients = {
{"create:copper_nugget", 63},
{"minecraft:gravel", 18},
},
addr = PRESS_ADDR,
},
["minecraft:netherrack"] = {
ingredients = {
{"create:cinder_flour", 64},
{"minecraft:cobblestone", 64},
},
addr = MIXER_ADDR,
},
["create:cinder_flour"] = {
ingredients = {
{"minecraft:netherrack", 64}
},
addr = CRUSHER_ADDR,
},
["minecraft:netherite_scrap"] = {
ingredients = {
{"minecraft:gravel", 2 * 64},
},
addr = CRUSHER_ADDR,
limit = 6,
},
["minecraft:nether_bricks"] = {
ingredients = {
{"minecraft:nether_brick", 64},
},
addr = PRESS_ADDR,
},
["oreganized:silver_nugget"] = {
ingredients = {
{"oreganized:silver_nugget", 60},
{"minecraft:gravel", 24},
},
addr = PRESS_ADDR,
},
["tfmg:nickel_nugget"] = {
ingredients = {
{"tfmg:nickel_nugget", 64},
{"minecraft:gravel", 64},
},
addr = PRESS_ADDR,
},
["tfmg:bauxite_powder"] = {
ingredients = {
{"tfmg:bauxite_powder", 64},
{"minecraft:gravel", 64},
},
addr = PRESS_ADDR,
limit = 6,
},
["minecraft:flint"] = {
ingredients = {
{"minecraft:gravel", 64},
},
addr = WASHER_ADDR,
limit = 8,
},
["minecraft:andesite"] = {
ingredients = {
{"minecraft:flint", 64},
{"minecraft:gravel", 32},
},
addr = PRESS_ADDR,
limit = 6,
},
}
local SLEEP_T = 20
function createModes (items)
local result = {}
for item, _ in pairs(items) do
result[item] = {"export", 0}
end
return result
end
function updateModes (current_modes, current_stock, first_run)
local lower_lim, upper_lim
local limits = {}
for item, _ in pairs(current_modes) do
if LIMIT_EXCEPTIONS[item] ~= nil then
lower_lim = LIMIT_EXCEPTIONS[item].lower
upper_lim = LIMIT_EXCEPTIONS[item].upper
else
lower_lim = GLOBAL_LIMS.lower
upper_lim = GLOBAL_LIMS.upper
end
limits[item] = {
lower = lower_lim,
upper = upper_lim,
}
end
for item, limits in pairs(limits) do
local count = current_stock[item]
if count == nil then count = 0 end
if count <= limits.lower then
current_modes[item] = {"recipe"}
elseif count >= limits.upper or first_run then
current_modes[item] = {
"export",
count - limits.lower,
}
end
end
end
function cycleItems (ticker, items)
local makeRequest
makeRequest = function (item, amt, addr, limit_override)
local limit = 64
if addr == MELTER_ADDR then limit = 9 end
if limit_override ~= nil then limit = limit_override end
if amt < limit then return end
local request = {
name = item,
_requestCount = limit
}
ticker.requestFiltered(addr, request)
os.sleep(1)
return makeRequest(item, amt - limit, addr, limit_override)
end
for _, pair in pairs(PRODUCTS) do
local name, addr, limit, keep = pair[1], pair[2], pair.limit, pair.keep
if items[name] ~= nil then
local amt = items[name]
if keep ~= nil then amt = amt - keep end
if amt < 0 then amt = 0 end
makeRequest(name, amt, addr, limit)
end
end
end
function getAmounts (storage_f)
local result = {}
for _, item in pairs(storage_f()) do
if result[item.name] == nil then result[item.name] = 0 end
result[item.name] = result[item.name] + item.count
end
return result
end
function getNumCraftable (ingredients, current_stock)
local result = nil
local item, count
for _, ingredient in ipairs(ingredients) do
item, count = ingredient[1], ingredient[2]
if current_stock[item] == nil then return 0 end
local num = math.floor(current_stock[item] / count)
if result == nil then
result = num
else
result = math.min(result, num)
end
end
if result == nil then result = 0 end
return result
end
function adjustStock (current_stock, ingredients, count)
if count == 0 then return end
local item, i_count
for _, ingredient in ipairs(ingredients) do
item, i_count = ingredient[1], ingredient[2]
current_stock[item] = current_stock[item] - (i_count * count)
end
end
function craftRecipe (ticker, recipe, current_stock)
local count = getNumCraftable(recipe.ingredients, current_stock)
if recipe.limit ~= nil then
count = math.min(count, recipe.limit)
end
adjustStock(current_stock, recipe.ingredients, count)
local createRequest
createRequest = function (recipe, i)
if i == nil then i = 1 end
local ingredient = recipe.ingredients[i]
if ingredient == nil then return end
local item = {
name = ingredient[1],
_requestCount = ingredient[2],
}
return item, createRequest(recipe, i + 1)
end
while count > 0 do
ticker.requestFiltered(recipe.addr, createRequest(recipe))
os.sleep(1)
count = count - 1
end
end
function export (ticker, item, amt)
if amt <= 0 then return end
local request = {
name = item,
_requestCount = amt
}
ticker.requestFiltered(EXPORT_ADDR, request)
end
function run (ticker, export_storage, current_modes, first_run)
if SPEEDOMETER ~= "" and peripheral.call(SPEEDOMETER, "getSpeed") == 0 then
os.sleep(SLEEP_T)
return run (ticker, export_storage, current_modes, first_run)
end
local export_amounts = getAmounts(export_storage.list)
local stock_amounts = getAmounts(ticker.stock)
updateModes(current_modes, stock_amounts, first_run)
for item, mode in pairs(current_modes) do
-- mode[1] is mode, mode[2] is amt_extra when exporting
if mode[1] == "recipe" then
-- make as many recipes as you can with current stock
local recipe = RECIPES[item]
craftRecipe(ticker, recipe, stock_amounts)
elseif mode[1] == "export" then
local export_amt = export_amounts[item]
if export_amt == nil then export_amt = 0 end
local amt_needed = KEEP_STOCKED[item] - export_amt
local amt = math.min(amt_needed, mode[2])
export(ticker, item, amt)
end
end
cycleItems(ticker, stock_amounts)
os.sleep(SLEEP_T)
return run (ticker, export_storage, current_modes)
end
if arg ~= nil and arg[1] == "run" then
local ticker = peripheral.wrap(STOCK_TICKER)
local export_storage = peripheral.wrap(EXPORT_STORAGE)
local current_modes = createModes(KEEP_STOCKED)
run(ticker, export_storage, current_modes, true)
end