mirror of
https://github.com/S4mpsa/InfOS.git
synced 2025-08-04 02:16:05 -04:00
280 lines
12 KiB
Lua
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% |