2020-10-30 21:33:29 +02:00

280 lines
12 KiB
Lua

comp=require("component"); event=require("event"); screen=require("term"); computer = require("computer"); thread = require("thread")
dict=require("dictionary"); line = require("transport"); config = require("configure")
function machine(address)
machineAddress = comp.get(address)
if(machineAddress ~= nil) then return comp.proxy(machineAddress) else return nil end
end
function findAddress(type)
for address, component in comp.list() do
if component == type then return address end
end
end
recipes = {}
fluidMap = {["fluid.molten.solderingalloy"] = {index = 81, size = 144},
["fluid.lubricant"] = {index = 80, size = 250},
["IC2 Coolant"] = {index = 79, size = 1000},
["fluid.molten.styrenebutadienerubber"] = {index = 78, size = 720},
["fluid.molten.niobiumtitanium"] = {index = 77, size = 144},
["fluid.molten.tritanium"] = {index = 76, size = 144}
}
local function addRecipe(slot, source, sourceSide)
if source.getStackInSlot(sourceSide, slot) ~= nil then
--screen.write("Adding a recipe\n")
local pattern = source.getStackInSlot(sourceSide, slot)
recipes[pattern.output] = {}
recipes[pattern.output]["label"] = pattern.output
recipes[pattern.output]["time"] = pattern.time
recipes[pattern.output]["inputs"] = 0
recipes[pattern.output]["fluids"] = 0
recipes[pattern.output]["tier"] = voltageToTier(pattern.eu)
if pattern.inputItems ~= nil then
local items = pattern.inputItems
for i = 1, #items, 1 do
--screen.write("Item "..i.." :"..items[i][1].." - "..items[i][2].."\n")
recipes[pattern.output]["input"..i] = {name = items[i][1], amount = items[i][2]}
recipes[pattern.output]["inputs"] = recipes[pattern.output]["inputs"] + 1
end
end
if pattern.inputFluids ~= nil then
local fluids = pattern.inputFluids
for i = 1, #fluids do
--screen.write("Fluid "..i.." :"..fluids[i][1].." - "..fluids[i][2].."\n")
recipes[pattern.output]["fluid"..i] = {name = fluids[i][1], amount = fluids[i][2]}
recipes[pattern.output]["fluids"] = recipes[pattern.output]["fluids"] + 1
end
end
end
end
function getRecipes(assemblyData)
if assemblyData["data"] ~= nil then
for i = 1, 16 do
addRecipe(i, assemblyData["data"], 0)
end
end
end
function copyPattern(interface, slot, recipe, database)
for i = 1, recipe.inputs, 1 do
local item = recipe["input"..i]
local name = item.name
if dictionary[name] ~= nil then name = dictionary[name] end
interface.setInterfacePatternInput(slot, database, databaseMap[name], item.amount, i)
end
end
local latestRecipe = {}
function processRecipe(assemblyData, recipe)
local inventory, database = assemblyData["inventory"], assemblyData["database"]
local needsConfiguring = false
if latestRecipe ~= nil then
if latestRecipe.label ~= recipe.label then
needsConfiguring = true
if latestRecipe.inputs ~= nil then
if latestRecipe.inputs > recipe.inputs then
line.clearInterfaces(assemblyData, recipe.inputs + 1, latestRecipe.inputs, latestRecipe.fluids - recipe.fluids, 4)
elseif latestRecipe.fluids > recipe.fluids then
line.clearInterfaces(assemblyData, 0, 0, recipe.fluids + 1, latestRecipe.fluids)
end
end
end
else
needsConfiguring = true
end
if needsConfiguring then
for i = 1, recipe["inputs"], 1 do
local item = recipe["input"..i]
local name = item.name
if dictionary[name] ~= nil then name = dictionary[name] end
if databaseMap[name] == nil then screen.write(" Updating database..."); updateDatabase(assemblyData, databaseMap); end
assemblyData["input"..i].setInterfaceConfiguration(1, database.address, databaseMap[name], item.amount)
screen.write(".")
end
for i = 1, recipe["fluids"], 1 do
local fluid = recipe["fluid"..i]
assemblyData["fluid"..i].setInterfaceConfiguration(1, database.address, fluidMap[fluid.name].index, fluid.amount/fluidMap[fluid.name].size)
screen.write(".")
end
if assemblyData["input15"].getInterfacePattern(1) ~= nil then
copyPattern(assemblyData["input15"], 1, recipe, database.address)
end
end
screen.write(" Inserting ...")
for i = 1, recipe["inputs"], 1 do
local item = recipe["input"..i]
assemblyData["inputTransposer"..i].transferItem(0, 1, item.amount, 1, 16)
screen.write(".")
end
for i = 1, recipe["fluids"], 1 do
local fluid = recipe["fluid"..i]
assemblyData["fluidTransposer"..i].transferItem(0, 1, fluid.amount/fluidMap[fluid.name].size, 1, 1)
screen.write(".")
end
os.sleep(1)
for i = 1, recipe["fluids"], 1 do
local fluid = recipe["fluid"..i]
assemblyData["fluidTransposer"..i].transferItem(1, 0, fluid.amount/fluidMap[fluid.name].size, 2, 9)
screen.write(".")
end
local recipeTicks = (recipe.time / math.pow(2, assemblyData.tier - recipe.tier))
if needsConfiguring == false then
os.sleep(recipeTicks / 20 - 1.5)
end
latestRecipe = recipe
line.waitForAssemblyline(recipeTicks - 50 , assemblyData["controller"])
end
function matchRecipe(recipeList, assemblyData, priority)
priority = priority or nil
local network = assemblyData["items"].getItemsInNetwork()
local size = #network * 2
if size == 0 then size = 1 end
foundItems = {}
for i = 1, #network, 1 do
foundItems[network[i].label] = network[i].size end
for i = 1, 15, 1 do
if assemblyData["inputTransposer"..i].getStackInSlot(0, 1) ~= nil then
local interfaceItem = assemblyData["inputTransposer"..i].getStackInSlot(0, 1)
if interfaceItem.size ~= nil then
if foundItems[interfaceItem.label] == nil then
foundItems[interfaceItem.label] = interfaceItem.size
else
foundItems[interfaceItem.label] = foundItems[interfaceItem.label] + interfaceItem.size
end
end
end
end
for recipeLabel, v in pairs(recipeList) do
local recipe, found = recipeList[recipeLabel], 0
local inputs = recipe.inputs
if debugMode then screen.write("Checking match for: "..recipeLabel.." with required N of "..recipe.inputs.."\n") end
for i = 1, inputs, 1 do
local label, requiredAmount = recipe["input"..i].name, recipe["input"..i].amount
if dictionary[label] ~= nil then label = dictionary[label] end
if debugMode then screen.write(" Searching for "..requiredAmount.." "..label) end
if foundItems[label] == nil then if debugMode then screen.write("\n") end break
else
local existingAmount = foundItems[label]
if existingAmount >= requiredAmount then
found = found + 1
if debugMode then screen.write(" | Found!: "..label.." N: "..found.."\n") end
else if debugMode then screen.write(" | Didn't find enough: "..existingAmount.."\n") end
end
end
end
if found == inputs then
if priority == nil then
return recipe
else
if priority.label == recipe.label then return recipe end
end
end
end
return nil
end
function voltageToTier(voltage)
local maxTier = 15
local tier = maxTier
voltage = voltage - 1
local tierVoltage = 32 * math.pow(4, tier - 1)
while voltage % tierVoltage == voltage do
tier = tier - 1
tierVoltage = 32 * math.pow(4, tier - 1)
end
return tier + 1
end
function getControllerTier(assemblyData)
local controller = assemblyData["controller"]
return voltageToTier(math.floor(string.gsub(string.sub(controller.getSensorInformation()[4], 1, string.find(controller.getSensorInformation()[4], "/")-1), "([^0-9]+)", "") + 0))
end
function refreshDatabase(assemblyData, databaseRef)
local database = assemblyData["database"]
local i = 2
local entry = database.get(i)
while database.get(i) ~= nil do
screen.write(".")
databaseRef[entry.label] = i
i = i + 1
entry = database.get(i)
end
end
function updateDatabase(assemblyData, databaseMap)
local chestSide = 5
if assemblyData["inventory"] ~= nil and assemblyData["database"] ~= nil then
local inventory, database = assemblyData["inventory"], assemblyData["database"]
for i = 1, inventory.getInventorySize(chestSide), 1 do
if inventory.getStackInSlot(chestSide, i) ~= nil then
inventory.store(chestSide, i, database.address, 1)
local hash = database.computeHash(1)
database.clear(1)
local index = database.indexOf(hash)
if index < 0 then
local j = 2
while database.get(j) ~= nil do
j = j + 1
end
inventory.store(chestSide, i, database.address, j)
databaseMap[inventory.getStackInSlot(chestSide, i).label] = j
end
end
end
end
end
function split(s, sep)
local fields = {}; local sep = sep or " "; local pattern = string.format("([^%s]+)", sep)
string.gsub(s, pattern, function(c) fields[#fields + 1] = c end)
return fields
end
function buildAssembly()
screen.write("Starting Assembly Line initalization...")
local assemblyStructure = {}
local file = io.open("addresses", "r")
if file == nil then
screen.write(" no address configuration found, configuring:\n")
config.getAddresses()
file = io.lines("addresses")
else
file = io.lines("addresses")
end
for line in file do
screen.write(".")
local tokens = split(line, ",")
assemblyStructure[tokens[1]] = machine(tokens[2])
end
screen.write("\n")
return assemblyStructure
end
function startAssembly(assemblyData)
assemblyData["tier"] = getControllerTier(assemblyData)
screen.write("Fetching recipes ... "); getRecipes(assemblyData); screen.write("Done")
databaseMap = {}
screen.write(" | Refreshing database ..."); refreshDatabase(assemblyData, databaseMap); screen.write(" Done")
screen.write(" | Clearing interfaces ... "); line.clearInterfaces(assemblyData); screen.write("Done")
debugMode = false
local cyclesSinceRefresh = 0
local configured = false
screen.write(" | Beginning operation\n")
while true do
local foundRecipe = matchRecipe(recipes, assemblyData)
if foundRecipe ~= nil then
screen.write("Starting assembly of "..foundRecipe.label.." ...")
processRecipe(assemblyData, foundRecipe)
screen.write(" Done!\n")
configured = true
else
if cyclesSinceRefresh > 20 then
getRecipes(assemblyData)
cyclesSinceRefresh = 0
end
cyclesSinceRefresh = cyclesSinceRefresh + 1
if configured then
configured = false
line.clearInterfaces(assemblyData)
latestRecipe = nil
end
os.sleep(5)
end
end
end
local assemblyLine = buildAssembly()
startAssembly(assemblyLine)
--Things to add:
--Make pattern match check for item sums instead of on a stack basis
--Add sanity check that everything was moved 100%