Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local term = require("term")
- local serial = require("serialization")
- _G.recipes = _G.recipes or {}
- local args = {...}
- local cmnd = args[1]
- table.remove(args,1)
- for i=1,#args do
- if tonumber(args[i]) then
- args[i] = tonumber(args[i])
- end
- end
- --[[main actions:
- get resources required for a craft/structure
- get crafting instructions for a craft
- get crafting instructions given you already have some resources
- ]]
- function addrecipe(name, outNum, ...)
- local inp = {...}
- local reqItems = {}
- for i=1,#inp,2 do
- table.insert(reqItems, { inp[i],inp[i+1] })
- end
- _G.recipes[name] = {outNum, reqItems}
- print("added recipe for " .. name)
- end
- function delrecipe(name)
- _G.recipes[name] = nil
- print("deleted recipe for " .. name)
- end
- function addResources(...)
- --add resource lists together
- local inp = {...}
- local final = {}
- for i=1,#inp do--for each inputed list
- for j=1,#inp[i] do--for each item
- --collect a list 'final' of the amount of each resource totaled.
- if final[ inp[i][j][1] ] then
- final[ inp[i][j][1] ] = final[ inp[i][j][1] ] + inp[i][j][2]
- else
- final[ inp[i][j][1] ] = inp[i][j][2]
- end
- end
- end
- --convert 'final' to a normal format of a list of resources
- local ret = {}
- for k,v in pairs(final) do
- table.insert(ret, {k, v})
- end
- return ret
- end
- function addSetResources(reqA, ...)
- --add resource lists to reqA
- local inp = {...}
- --make a map for reqA
- local mp = {}
- for i=1,#reqA do
- mp[reqA[i][1]] = i
- end
- for i=1,#inp do--for each inputed list
- for j=1,#inp[i] do--for each item
- if mp[ inp[i][j][1] ] then--if we know where that resource is in reqA
- --add to the amount of that resource
- reqA[ mp[inp[i][j][1]] ][2] =
- reqA[ mp[inp[i][j][1]] ][2] + inp[i][j][2]
- else --add a new item to reqA
- mp[ inp[i][j][1] ] = #reqA+1
- reqA[#reqA+1] = {inp[i][j][1], inp[i][j][2]}
- end
- end
- end
- end
- function multResources(req, num)
- --multiply resource amounts in req
- for i=1,#req do
- req[i][2] = req[i][2] * num
- end
- end
- function useSetResources(use, goal)
- if not goal or #goal == 0 then return end
- --make a map for use
- local mpU = {}
- for i=1,#use do
- mpU[use[i][1]] = i
- end
- --make a map for goal
- local mpG = {}
- for i=1,#goal do
- mpG[goal[i][1]] = i
- end
- --use the resources to craft goal
- local remU, remG = {}, {}
- for k,v in pairs(mpU) do
- if mpG[k] then--for each resource in both
- local nU, nG = use[mpU[k]][2], goal[mpG[k]][2]
- if nG > nU then--if goal's resource > use's resource
- --set goal's to goal's - use's
- goal[mpG[k]][2] = goal[mpG[k]][2] - nU
- table.insert(remU, k)
- --table.remove(use, mpU[k])
- elseif nG == nU then
- --they cancel out equally
- table.insert(remG, k)
- --table.remove(goal, mpG[k])
- table.insert(remU, k)
- --table.remove(use, mpU[k])
- else
- --subtract that many from use
- table.insert(remG, k)
- --table.remove(goal, mpG[k])
- use[mpU[k]][2] = use[mpU[k]][2] - nG
- end
- end
- end
- --remove spent stuff
- for i=1,#remU do
- for j=1,#use do
- if use[j] and use[j][1] == remU[i] then
- table.remove(use, j)
- end
- end
- end
- for i=1,#remG do
- for j=1,#goal do
- if goal[j] and goal[j][1] == remG[i] then
- table.remove(goal, j)
- end
- end
- end
- end
- function calc(resource, amount, have)
- amount = amount or 1
- local requirements = {}
- if _G.recipes[resource] then
- local mat = _G.recipes[resource]
- for i=1,#mat[2] do
- local subReq = calc(mat[2][i][1], mat[2][i][2] * (amount/mat[1]), have)
- useSetResources(subReq, have)
- addSetResources(requirements, subReq)
- end
- else
- local subReq = {{resource, amount}}
- useSetResources(subReq, have)
- addSetResources(requirements, subReq)
- end
- return requirements
- end
- function oneCalc(resource, amount)
- local requirements = {}
- if _G.recipes[resource] then
- local mat = _G.recipes[resource]
- for i=1,#mat[2] do
- local subReq = {mat[2][i][1], mat[2][i][2] * (amount/mat[1])}
- addSetResources(requirements, subReq)
- end
- else
- table.insert(requirements, {resource, amount})
- end
- return requirements
- end
- local textY = 3
- function printLineWait(text)
- print(text)
- textY = textY + 1
- local view = {term.getViewport()}
- local h = view[2]
- if textY > h then
- term.read({ dobreak = true })
- textY = 3
- end
- end
- function stackNumbers(num)
- if type(num) ~= "number" then
- if tonumber(num) then
- num = tonumber(num)
- else
- print(num.." is not a number")
- end
- end
- local ret = ""
- if num > 64 then
- for i=1,math.floor(num/64) do
- ret = ret.."64".." "
- end
- ret = ret..(num%64)
- if num%64 == 0 then
- ret = string.sub(ret, 1, #ret-2)
- end
- else
- ret = num
- end
- return ret
- end
- function printResources(req)
- if #req == 0 then
- printLineWait("Resources: none.")
- return
- end
- printLineWait("Resources:")
- local enChar = ","
- for i=1,#req do
- if #req == 1 then enChar = ""
- elseif #req == i then enChar = "." end
- printLineWait(stackNumbers(req[i][2]) .. " " .. req[i][1]..enChar)
- end
- end
- function addSetCrafting(crfA, ...)
- --add crafting lists to crfA
- local inp = {...}
- --make a map for crfA
- local mp = {}
- for i=1,#crfA do
- mp[crfA[i][1]] = i
- end
- for i=1,#inp do--for each inputed list
- for j=1,#inp[i] do--for each item
- local ind = mp[ inp[i][j][1] ]
- if ind then--if we know where that resource is in crfA
- --add to the amount of that resource
- crfA[ ind ][2] = crfA[ ind ][2] + inp[i][j][2]
- if crfA[ ind ][3] < inp[i][j][3] then
- --crfA gets highest tier for each material
- crfA[ ind ][3] = inp[i][j][3]
- end
- else --add a new item to crfA
- mp[ inp[i][j][1] ] = #crfA+1
- crfA[#crfA+1] = {inp[i][j][1], inp[i][j][2], inp[i][j][3]}
- end
- end
- end
- end
- function calcCrafting(resource, amount, tier)
- --[[
- like calc(), but collects craftable items
- items are given a tier
- when merged, select higher tier
- ]]
- tier = tier or 1
- local requirements = {}
- if _G.recipes[resource] then--if this item has a recipe
- --add itself to the requirements
- addSetCrafting(requirements, {{resource, amount, tier}})
- local mat = _G.recipes[resource]
- for i=1,#mat[2] do--add its requirements to the requirements
- local subReq = calcCrafting(mat[2][i][1],
- mat[2][i][2] * (amount/mat[1]),
- tier + 1)--later recipes have higher tier
- addSetCrafting(requirements, subReq)
- end
- else--no recipe for this
- requirements = {}
- end
- return requirements
- end
- function printCrafting(crf)
- --sort by largest tier first
- table.sort(crf, function(a,b) return a[3] > b[3] end)
- printLineWait("Crafting:")
- --print crafting
- local curTier = 0
- for i=1,#crf do
- if crf[i][3] ~= curTier then
- curTier = crf[i][3]
- printLineWait("Tier "..curTier..":")
- end
- printLineWait("craft "..stackNumbers(crf[i][2]).." "..crf[i][1])
- end
- end
- function listRecipes()
- printLineWait("Recipes:")
- for k,v in pairs(_G.recipes) do
- printLineWait(k)
- --printLineWait(v[1])--amount it crafts
- --printLineWait(#v[2])--number of types of materials
- --printResources(v[2])
- end
- end
- function recipeDetail(item)
- if _G.recipes[item] then
- printLineWait("Recipe: "..item)
- printResources(_G.recipes[item][2])
- else
- printLineWait("I don't know about "..item..".")
- end
- end
- function stringSplit(inputstr, sep)
- if sep == nil then
- sep = "%s"
- end
- local t={}
- for str in string.gmatch(inputstr..sep, "([^"..sep.."]*)"..sep) do
- --print("\""..str.."\"")
- table.insert(t,str)
- end
- return t
- end
- function saveRecipes()
- local file = io.open("craftingRecipes.txt","w")
- file:write(serial.serialize(_G.recipes))
- file:close()
- end
- function loadRecipes()
- local file = io.open("craftingRecipes.txt","r")
- _G.recipes = serial.unserialize(file:read("*a"))
- file:close()
- end
- cmdList = {}
- local function listCommands()
- print("commands:")
- for k,v in pairs(cmdList) do
- print(" "..v)
- end
- end
- local commands = {
- save = saveRecipes,
- load = loadRecipes,
- calculate = function(...)
- local args = {...}
- printResources( calc(args[1],args[2]) )
- printCrafting( calcCrafting(args[1],args[2]) )
- end,
- fullcalculate = function(...)
- local args = {...}
- print("what do you have?")
- local have = stringSplit(term.read(), ' ')
- local haveItems = {}
- for i=1,#have,2 do
- table.insert(haveItems, { have[i],tonumber(have[i+1]) })
- end
- printResources(calc( args[1], args[2], haveItems ))
- printCrafting(calcCrafting( args[1], args[2], haveItems ))
- end,
- setrecipe = addrecipe,
- setstructure = function(name, ...)
- addrecipe(name, 1, ...)
- end,
- delrecipe = delrecipe,
- delstructure = delrecipie,
- listrecipes = listRecipes,
- recipedetail = recipeDetail,
- commands = listCommands,
- exit = function() end--dummy function, never called
- }
- for k,v in pairs(commands) do--fill cmdList with list of commands
- table.insert(cmdList, k)
- end
- if cmnd and commands[cmnd] then--if a cmnd exists
- --run it with args as inputs
- commands[cmnd]( table.unpack(args) )
- else--no command, go into program loop
- print("type \"commands\" for commands,")
- print("type \"exit\" to exit.")
- local doExit = false
- --while they haven't typed "exit", do this loop
- while not doExit do
- --take input of multiple items separated by spaces
- local args = stringSplit(term.read(), "%s")
- --print(#args)
- if args[1] then--if they typed at least one thing
- if args[1] == "exit" then break end
- local cmnd = args[1]
- table.remove(args,1)
- if cmnd and commands[cmnd] then--if a cmnd exists
- --run it with args as inputs
- print("running "..cmnd)
- commands[cmnd]( table.unpack(args) )
- end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement