195 lines
5.9 KiB
Lua
195 lines
5.9 KiB
Lua
-- Program to control a compacting storage made with create.
|
|
|
|
-- NOTE: set block -> ingot refresh amount higher than the level desired in
|
|
-- this program to prioritize using available resources before generating
|
|
-- new ones
|
|
|
|
-- constants
|
|
|
|
local MAIN_TICKER = ""
|
|
local REQUEST_TICKER = ""
|
|
local STORAGE_ADDRESS = ""
|
|
local SLEEP_TIME = 30
|
|
local NUGGET_RATIO = 63 -- amount of nuggets per craft
|
|
local BLOCK_RATIO = 7 -- amount of blocks per craft
|
|
local ITEM_TYPES = { "iron", "copper", "zinc", "gold", "electrum" }
|
|
|
|
local STACKS = 64
|
|
local NUGGETS = 1
|
|
local INGOTS = 9
|
|
local BLOCKS = 81
|
|
|
|
-- V2!! what am i working on?
|
|
-- TODO new oregen interop: request from REQUEST_TICKER to get new ore
|
|
-- TODO new way to keep items stocked: request from MAIN_TICKER
|
|
-- do I even need a specific inventory anymore? I could maybe move metals
|
|
-- into the sophisticated storage setup.
|
|
-- TODO new way to craft between states: make requests with MAIN_TICKER
|
|
-- (could maybe add a redstone requester if desired)
|
|
|
|
-- Levels
|
|
local MIN_NUM = (4 * STACKS * NUGGETS) + (4 * STACKS * INGOTS)
|
|
local MAX_NUM = (8 * STACKS * NUGGETS) + (8 * STACKS * INGOTS)
|
|
|
|
-- basic actions
|
|
function craft (item_type, conversion_type)
|
|
-- TODO rework
|
|
end
|
|
|
|
function craft_multiple (item_type, conversion_type, count)
|
|
if count < 1 then
|
|
return
|
|
else
|
|
craft(item_type, conversion_type)
|
|
os.sleep(1)
|
|
return craft_multiple(item_type, conversion_type, count - 1)
|
|
end
|
|
end
|
|
|
|
function execute_crafts (item_type, crafts)
|
|
local num_crafts = crafts.nuggets
|
|
if num_crafts > 0 then
|
|
print(("Crafting %s nuggets"):format(item_type))
|
|
craft_multiple(item_type, 4, num_crafts)
|
|
elseif num_crafts < 0 then
|
|
print(("Crafting %s ingots"):format(item_type))
|
|
craft_multiple(item_type, 1, -num_crafts)
|
|
end
|
|
num_crafts = crafts.blocks
|
|
if num_crafts > 0 then
|
|
print(("Crafting %s blocks"):format(item_type))
|
|
craft_multiple(item_type, 2, num_crafts)
|
|
elseif num_crafts < 0 then
|
|
print(("Crafting %s ingots"):format(item_type))
|
|
craft_multiple(item_type, 3, -num_crafts)
|
|
end
|
|
end
|
|
|
|
function request_more (ticker, item_type)
|
|
local request = {
|
|
name = {
|
|
_op = "regex",
|
|
value = ".*:" .. item_type .. "_nugget"
|
|
}
|
|
}
|
|
ticker.requestFiltered(STORAGE_ADDRESS, request)
|
|
end
|
|
|
|
-- logic
|
|
|
|
function sum_items (inv_f)
|
|
local result = {}
|
|
for _, item in pairs(inv_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 dist_to_num (dist)
|
|
return dist.nuggets + dist.ingots * INGOTS + dist.blocks * BLOCKS
|
|
end
|
|
|
|
function get_dist (item_type, items)
|
|
-- TODO change plurals to singulars to match mc
|
|
local dist = { nuggets = 0, ingots = 0, blocks = 0 }
|
|
for item, count in pairs(items) do
|
|
local type, form = item:match":(%l-)_(%l*)"
|
|
form = string.format("%ss", form)
|
|
if type == item_type and dist[form] ~= nil then
|
|
dist[form] = dist[form] + count
|
|
end
|
|
end
|
|
return dist
|
|
end
|
|
|
|
function decide_dist (num)
|
|
local dist = { nuggets = 0, ingots = 0, blocks = 0 }
|
|
if num > MAX_NUM then
|
|
local excess = num - MAX_NUM
|
|
dist.blocks = math.floor(excess / BLOCKS)
|
|
num = num - (dist.blocks * BLOCKS)
|
|
end
|
|
local balance = math.floor(num / 10)
|
|
dist.nuggets, dist.ingots = balance, balance
|
|
num = num - (balance * 10)
|
|
dist.nuggets = dist.nuggets + num
|
|
return dist
|
|
end
|
|
|
|
function get_diff (dist1, dist2)
|
|
return {
|
|
nuggets = dist1.nuggets - dist2.nuggets,
|
|
ingots = dist1.ingots - dist2.ingots,
|
|
blocks = dist1.blocks - dist2.blocks
|
|
}
|
|
end
|
|
|
|
function filter_clamp (diff, current_dist)
|
|
-- reduce diff numbers to what can be crafted using current resources
|
|
if diff.blocks > 0 then
|
|
diff.blocks = math.min(
|
|
diff.blocks - (diff.blocks % BLOCK_RATIO),
|
|
math.floor(current_dist.ingots / 9)
|
|
)
|
|
end
|
|
if diff.nuggets > 0 then
|
|
diff.nuggets = math.min(
|
|
diff.nuggets - (diff.nuggets % NUGGET_RATIO),
|
|
current_dist.ingots * 9
|
|
)
|
|
end
|
|
diff.ingots = (-diff.nuggets / 9) + (-diff.blocks * 9)
|
|
return diff
|
|
end
|
|
|
|
function diff_to_crafts (diff)
|
|
-- go from one end e.g. nuggets to the other e.g. blocks, removing
|
|
-- from the diff to create crafts until the diff is empty
|
|
local crafts = {}
|
|
crafts.nuggets = math.floor(diff.nuggets / NUGGET_RATIO)
|
|
crafts.blocks = math.floor(diff.blocks / BLOCK_RATIO)
|
|
return crafts
|
|
end
|
|
|
|
function print_counts (items)
|
|
for item, amount in pairs(items) do
|
|
local type, form = string.match(item, ":(%l+)_(%l+)")
|
|
if type ~= nil and form ~= nil then
|
|
print(("%s %s: %d"):format(type, form, amount))
|
|
end
|
|
end
|
|
end
|
|
|
|
local main_t = peripheral.wrap(MAIN_TICKER)
|
|
local request_t = peripheral.wrap(REQUEST_TICKER)
|
|
local requesting = {}
|
|
while true do
|
|
-- 1. Sum items in inventory and organize by item type
|
|
local items = sum_items(main_t.stock)
|
|
-- print_counts(items)
|
|
|
|
-- 2. either work towards a desired distribution or create more resources
|
|
for _, item_type in ipairs(ITEM_TYPES) do
|
|
local current_dist = get_dist(item_type, items)
|
|
local num = dist_to_num(current_dist)
|
|
if num > MIN_NUM then
|
|
local desired_dist = decide_dist(num)
|
|
local diff = get_diff(desired_dist, current_dist)
|
|
diff = filter_clamp(diff, current_dist)
|
|
local crafts = diff_to_crafts(diff)
|
|
execute_crafts(item_type, crafts)
|
|
elseif num > MAX_NUM then
|
|
-- keep requesting until above MAX_NUM
|
|
requesting[item_type] = nil
|
|
else
|
|
requesting[item_type] = true
|
|
end
|
|
if requesting[item_type] then
|
|
request_more(request_t, item_type)
|
|
end
|
|
end
|
|
|
|
-- sleep until next cycle
|
|
os.sleep(SLEEP_TIME)
|
|
end
|