Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ===========================
- -- == autoCraft (2018/05/20 unfinished version)
- -- ===========================
- -- -----------------------
- -- config
- -- -----------------------
- DATA_FILE_NAME = "atCra.dat"
- -- -----------------------
- -- utility
- -- -----------------------
- local function fileReadAll(filePath)
- local hFile = fs.open(filePath, "r")
- if nil == hFile then
- return ""
- end
- local txt = hFile.readAll()
- hFile.close()
- return txt
- end
- local function fileOverwrite(fileName, text)
- local hFile = fs.open(fileName, "w")
- hFile.writeLine(text)
- hFile.close()
- end
- -- ---------------
- -- Logger
- -- ---------------
- -- do logging?
- DEBUG__DO_LOGGING = true
- -- local log
- DEBUG__LOCAL_ENABLED = true
- DEBUG__LOCAL_LOG_FILE_NAME = "debug.log"
- -- remote log
- DEBUG__REMOTE_ENABLED = false
- DEBUG__REMOTE_ADDR = 20
- DEBUG__REMOTE_MODEM_DIR = "right"
- function debug(txt)
- if DEBUG__DO_LOGGING then
- if DEBUG__LOCAL_ENABLED then
- local hFile
- if fs.exists(DEBUG__LOCAL_LOG_FILE_NAME) then
- hFile = fs.open(DEBUG__LOCAL_LOG_FILE_NAME, "a");
- else
- hFile = fs.open(DEBUG__LOCAL_LOG_FILE_NAME, "w");
- end
- hFile.writeLine(txt);
- hFile.close();
- end
- if DEBUG__REMOTE_ENABLED then
- rednet.open(DEBUG__REMOTE_MODEM_DIR)
- rednet.send(DEBUG__REMOTE_ADDR, txt)
- rednet.close()
- end
- end
- end
- -- -----------------------
- -- application data
- -- -----------------------
- local ingredientsList
- -- -----------------------
- -- application
- -- -----------------------
- -- ---------------
- -- saveData
- -- ---------------
- local function saveData(the_db)
- fileOverwrite(DATA_FILE_NAME, textutils.serialize(the_db))
- end
- -- ---------------
- -- loadData
- -- ---------------
- local function loadData()
- return textutils.unserialize(fileReadAll(DATA_FILE_NAME))
- end
- -- ---------------
- -- makeKey
- -- ---------------
- function makeKey(name, damage)
- return name .. "@" .. damage
- end
- -- ---------------
- -- check
- -- ---------------
- function check()
- for _, v in pairs({ 4,8,12,13,14,15,16 }) do
- if 0 < turtle.getItemCount(v) then
- print("Don't use slot 4,8,12,13,14,15,16.")
- return false
- end
- end
- if false == turtle.craft(0) then
- print("not craftable.")
- return false
- end
- return true
- end
- -- ---------------
- -- doCraft
- -- ---------------
- function doCraft()
- local bfr = { }
- for i = 1, 16 do
- bfr[i] = turtle.getItemDetail(i)
- end
- turtle.craft(1)
- local aft = { }
- for i = 1, 16 do
- aft[i] = turtle.getItemDetail(i)
- end
- return bfr, aft
- end
- -- ---------------
- -- getDetail
- -- ---------------
- function getDetail(bfr, aft)
- local crafted_idx = { }
- local ingredients_idx = { }
- for i = 1, 16 do
- if nil ~= aft[i]
- and (nil == bfr[i] or (aft[i].name ~= bfr[i].name or aft[i].damage ~= bfr[i].damage)) then
- table.insert(crafted_idx, i)
- end
- if nil ~= bfr[i] then
- table.insert(ingredients_idx, i)
- end
- end
- -- ------------------------------------
- local crafted = { }
- for _, idx in ipairs(crafted_idx) do
- local key = makeKey(aft[idx].name, aft[idx].damage)
- if nil == crafted[key] then
- crafted[key] = { }
- crafted[key].name = aft[idx].name
- crafted[key].damage = aft[idx].damage
- crafted[key].count = 0
- end
- crafted[key].count = crafted[key].count + aft[idx].count
- end
- -- ------------------------------------
- local ingredients = { }
- local symbols = { "A","B","C","D","E","F","G","H","I" }
- local symbol_index = 0
- local count
- for _, idx in ipairs(ingredients_idx) do
- local key = makeKey(bfr[idx].name, bfr[idx].damage)
- if nil == ingredients[key] then
- ingredients[key] = { }
- ingredients[key].name = bfr[idx].name
- ingredients[key].damage = bfr[idx].damage
- ingredients[key].count = 0
- symbol_index = symbol_index + 1
- ingredients[key].symbol = symbols[symbol_index]
- end
- if nil == aft[idx] then
- count = bfr[idx].count
- elseif aft[idx].name ~= bfr[idx].name or aft[idx].damage ~= bfr[idx].damage then
- count = bfr[idx].count
- elseif aft[idx].name == bfr[idx].name and aft[idx].damage == bfr[idx].damage then
- count = bfr[idx].count - aft[idx].count
- end
- ingredients[key].count = ingredients[key].count + count
- bfr[idx].symbol = ingredients[key].symbol
- end
- return ingredients, crafted
- end
- -- ---------------
- -- horizontalCheck
- -- ---------------
- function horizontalCheck(recipe, y)
- for x = 1, 3 do
- if "-" ~= recipe[y][x] then
- return true
- end
- end
- return false
- end
- -- ---------------
- -- verticalCheck
- -- ---------------
- function verticalCheck(recipe, x)
- for y = 1, 3 do
- if "-" ~= recipe[y][x] then
- return true
- end
- end
- return false
- end
- -- ---------------
- -- getRecipe
- -- ---------------
- local function getRecipe(bfr)
- local recipe = { }
- for i = 0, 2 do
- local line = { }
- for j = 0, 2 do
- local idx = i * 4 + j + 1
- if nil ~= bfr[idx] then
- line[j + 1] = bfr[idx].symbol
- else
- line[j + 1] = "-"
- end
- end
- recipe[i+1] = line
- end
- local crop_top = 1
- local crop_bottom = 3
- local crop_left = 1
- local crop_right = 3
- for x = 1, 3 do
- if verticalCheck(recipe, x) then
- crop_left = x
- break
- end
- end
- for x = 3, 1, -1 do
- if verticalCheck(recipe, x) then
- crop_right = x
- break
- end
- end
- for y = 1, 3 do
- if horizontalCheck(recipe, y) then
- crop_top = y
- break
- end
- end
- for y = 3, 1, -1 do
- if horizontalCheck(recipe, y) then
- crop_bottom = y
- break
- end
- end
- local recipe_slim = { }
- for y = crop_top, crop_bottom do
- i = y - crop_top + 1
- local line = { }
- for x = crop_left, crop_right do
- j = x - crop_left + 1
- line[j] = recipe[y][x]
- end
- recipe_slim[i] = line
- end
- return recipe, recipe_slim
- end
- -- ---------------
- -- regist detail
- -- ---------------
- local function registDetail(the_db, ingredients_or_crafted, mark)
- local new_count = 0
- for k, v in pairs(ingredients_or_crafted) do
- local dat = the_db[k]
- print("[" .. mark .. "]" .. k)
- if nil == dat then
- term.write("Input alias (or blank) > ")
- line = read()
- if "" ~= line then
- alias = line
- else
- alias = "(no alias)"
- print("no alias")
- end
- the_db[k] = {}
- the_db[k].name = v.name
- the_db[k].damage = v.damage
- the_db[k].alias = alias
- new_count = new_count + 1
- else
- print("alias = [" .. dat.alias .. "]")
- end
- end
- return new_count
- end
- -- ---------------
- -- compareIngredients()
- -- ---------------
- local function compareIngredients(ingredients_A, ingredients_B)
- for key_A, dat_A in pairs(ingredients_A) do
- local dat_B = ingredients_B[key_A]
- if nil == dat_B then
- return false
- end
- if dat_A.count ~= dat_B.count then
- return false
- end
- end
- return true
- end
- -- ---------------
- -- copyIngredients
- -- ---------------
- local function copyIngredients(ingredients)
- local ret = { }
- for k, v in pairs(ingredients) do
- local dat = { }
- dat.name = v.name
- dat.damage = v.damage
- dat.symbol = v.symbol
- dat.count = v.count
- ret[k] = dat
- end
- return ret
- end
- -- ---------------
- -- copyRecipe
- -- ---------------
- local function copyRecipe(recipe)
- local ret = { }
- for i, v in ipairs(recipe) do
- local line = { }
- for j, vv in ipairs(v) do
- table.insert(line, vv)
- end
- table.insert(ret, line)
- end
- return ret
- end
- -- ---------------
- -- makeRecipeData
- -- ---------------
- local function makeCraftData(registered_recipes, new_ingredients, new_recipe_slim)
- local is_new_uniq_recipe = true
- for _, registerd_r in pairs(registered_recipes) do
- if "craft" == registerd_r.type then
- local rslt_A = compareIngredients(registerd_r.ingredients, new_ingredients)
- local rslt_B = compareIngredients(new_ingredients, registerd_r.ingredients)
- if true == (rslt_A and rslt_B) then
- is_new_uniq_recipe = false
- break
- end
- end
- end
- if true == is_new_uniq_recipe then
- local data = {}
- data.type = "craft"
- --[x] data.ingredients = new_ingredients
- --[x] data.recipe_slim = new_recipe_slim
- --[x] data.ingredients = { unpack(new_ingredients) }
- --[x] data.recipe_slim = { unpack(new_recipe_slim) }
- data.ingredients = copyIngredients(new_ingredients)
- data.recipe_slim = copyRecipe(new_recipe_slim)
- return data
- else
- return nil
- end
- end
- -- ---------------
- -- craft
- -- ---------------
- local function craft(the_db)
- debug("craft -----------------------------")
- if false == check() then
- return
- end
- local bfr, aft = doCraft()
- local ingredients, crafted = getDetail(bfr, aft)
- local recipe, recipe_slim = getRecipe(bfr)
- debug("ingredients = " .. textutils.serialize(ingredients))
- debug("crafted = " .. textutils.serialize(crafted))
- debug("recipe = " .. textutils.serialize(recipe))
- debug("recipe_slim = " .. textutils.serialize(recipe_slim))
- registDetail(the_db, ingredients, "I")
- registDetail(the_db, crafted, "C")
- local data
- for k, v in pairs(crafted) do
- local re = the_db[k].recipes
- if nil == re then
- the_db[k].recipes = { }
- end
- data = makeCraftData(the_db[k].recipes, ingredients, recipe_slim)
- if nil ~= data then
- table.insert(the_db[k].recipes, data)
- end
- end
- saveData(the_db)
- end
- -- ---------------
- -- promptLearn
- -- ---------------
- local function promptLearn(the_db)
- while true do
- term.clear()
- term.setCursorPos(1, 1)
- print([[autoCraft ~ [learn craft]
- 1 : [c]raft
- 2 : smelt
- 3 : dig
- 4 : bucket
- 5 : spill
- b : back to main menu
- x : e[x]it]])
- term.write("input and hit enter key.>")
- input = read()
- if "1" == input or "c" == input then
- craft(the_db)
- elseif "b" == input then
- return true
- elseif "x" == input then
- return false
- else
- print("wrong input.")
- end
- end
- end
- -- =================================
- -- ingredients
- -- =================================
- local detailCountList = { }
- local currentReadyIsPrimaryChest = true
- local primaryChest = { }
- primaryChest.suckFunc = turtle.suck
- primaryChest.dropFunc = turtle.drop
- local secondaryChest = { }
- secondaryChest.suckFunc = turtle.suckDown
- secondaryChest.dropFunc = turtle.dropDown
- -- ---------------
- -- existsBlankSlot
- -- ---------------
- local function existsBlankSlot()
- for i = 1, 16 do
- if 0 == turtle.getItemCount(i) then
- return true
- end
- end
- return false
- end
- -- ---------------
- -- clearTurtleSlot
- -- ---------------
- local function clearTurtleSlot(toChest, detailCountList)
- if nil == detailCountList then
- detailCountList = { }
- end
- for i = 1, 16 do
- local beforeCount = turtle.getItemCount(i)
- if 0 < beforeCount then
- local det = turtle.getItemDetail(i)
- local key = makeKey(det.name, det.damage)
- if nil == detailCountList[key] then
- detailCountList[key] = 0
- end
- turtle.select(i)
- local rslt = toChest.dropFunc()
- local afterCount = turtle.getItemCount(i)
- detailCountList[key] = detailCountList[key] + beforeCount - afterCount
- if false == rslt then
- turtle.select(1)
- return false
- end
- end
- end
- turtle.select(1)
- return true
- end
- -- ---------------
- -- doMoveItems
- -- ---------------
- local function doMoveItems(fromChest, toChest, pickupList)
- local detailCountList = { }
- while true do
- local rslt = fromChest.suckFunc()
- if false == rslt then
- if existsBlankSlot() then
- break
- else
- rslt = clearTurtleSlot(toChest, detailCountList)
- if false == rslt then
- return false, detailCountList
- end
- end
- end
- end
- local rslt = clearTurtleSlot(toChest, detailCountList)
- if false == rslt then
- return false, detailCountList
- else
- return true, detailCountList
- end
- end
- -- ---------------
- -- moveItems
- -- ---------------
- local function moveItems(fromChest, toChest)
- return doMoveItems(fromChest, toChest, nil)
- end
- -- ---------------
- -- pickupItems
- -- ---------------
- local function pickupItems(fromChest, toChest, pickupList)
- return doMoveItems(fromChest, toChest, pickupList)
- end
- -- ---------------
- -- updateIngredientsInfo
- -- ---------------
- local function updateIngredientsInfo()
- local rslt = clearTurtleSlot(secondaryChest)
- if false == rslt then
- print("too many items.(1)")
- end
- rslt = moveItems(primaryChest, secondaryChest)
- if false == rslt then
- print("too many items.(2)")
- end
- rslt, list = moveItems(secondaryChest, primaryChest)
- if false == rslt then
- print("too many items.(3)")
- end
- return list
- end
- -- ---------------
- -- makeList
- -- ---------------
- local function makeList(associativerray)
- local list = { }
- for k, v in pairs(associativerray) do
- local dat = { }
- dat.key = k
- dat.value = v
- table.insert(list, dat)
- end
- return list
- end
- -- ---------------
- -- getAlias
- -- ---------------
- local function getAlias(the_db, key)
- local dat = the_db[key]
- if nil == dat then
- return key
- end
- if nil == dat.alias then
- return key
- end
- return dat.alias
- end
- -- ---------------
- -- promptListIngredients
- -- ---------------
- local function promptListIngredients(the_db)
- local currentPage = 1
- local w, h = term.getSize()
- local pageSize = h - 5
- local ingreList = makeList(ingredientsList)
- while true do
- term.clear()
- term.setCursorPos(1, 1)
- local pageTotal = math.ceil(#ingreList / pageSize)
- print("[list ingredients] page " .. currentPage .. " of " .. pageTotal)
- local firstItem = (currentPage - 1) * pageSize + 1
- local lastItem = math.min(firstItem + pageSize - 1, #ingreList)
- for i = firstItem, lastItem do
- local dat = ingreList[i]
- local alias = getAlias(the_db, dat.key)
- print("[" .. i .. "] / " .. alias .. " / " .. dat.value)
- end
- print([[u : update list
- [n]ext / [p]revious page
- [b]ack to main menu / e[x]it]])
- term.write("input number and hit enter key.>")
- local input = read()
- if "u" == input then
- ingredientsList = updateIngredientsInfo()
- ingreList = makeList(ingredientsList)
- elseif "n" == input then
- currentPage = math.min(currentPage + 1, pageTotal)
- elseif "p" == input then
- currentPage = math.max(currentPage - 1, 1)
- elseif "b" == input then
- return true
- elseif "x" == input then
- return false
- else
- print("wrong input.")
- end
- end
- end
- -- =================================
- -- autoCraft
- -- =================================
- -- ---------------
- -- makeCraftList
- -- ---------------
- local function makeCraftList(the_db)
- local list = { }
- for key, val in pairs(the_db) do
- if nil ~= val.recipes then
- local dat = { }
- dat.key = key
- dat.alias = val.alias
- table.insert(list, dat)
- end
- end
- return list
- end
- -- ---------------
- -- promptAutoCraft
- -- ---------------
- local function promptAutoCraft(the_db)
- local craftList = makeCraftList(the_db)
- local currentPage = 1
- local w, h = term.getSize()
- local pageSize = h - 5
- while true do
- term.clear()
- term.setCursorPos(1, 1)
- local pageTotal = math.ceil(#craftList / pageSize)
- local firstItem = (currentPage - 1) * pageSize + 1
- local lastItem = math.min(firstItem + pageSize - 1, #craftList)
- print("[auto craft] page " .. currentPage .. " of " .. pageTotal)
- for i = firstItem, lastItem do
- local dat = craftList[i]
- print("[" .. i .. "] " .. dat.alias)
- end
- print([[[n]ext / [p]revious page
- [b]ack to main menu / e[x]it]])
- term.write("input number and hit enter key.>")
- local input = read()
- if "n" == input then
- currentPage = math.min(currentPage + 1, pageTotal)
- elseif "p" == input then
- currentPage = math.max(currentPage - 1, 1)
- elseif "b" == input then
- return true
- elseif "x" == input then
- return false
- else
- print("wrong input.")
- end
- end
- end
- -- =================================
- -- main menu
- -- =================================
- -- ---------------
- -- promptMainMenu
- -- ---------------
- local function promptMainMenu(the_db, ingredientsList)
- while true do
- term.clear()
- term.setCursorPos(1, 1)
- print([[autoCraft ~ [main menu]
- 1 : auto [c]raft
- 2 : list [i]ngredients
- 3 : [l]earn
- 4 : [e]dit data
- x : e[x]it]])
- term.write("input number and hit enter key.>")
- input = read()
- if "1" == input or "c" == input then
- if false == promptAutoCraft(the_db) then
- return false
- end
- elseif "2" == input or "i" == input then
- if false == promptListIngredients(the_db) then
- return false
- end
- elseif "3" == input or "l" == input then
- if false == promptLearn(the_db) then
- return false
- end
- elseif "x" == input then
- return
- else
- print("wrong input.")
- end
- end
- end
- -- ---------------
- -- listItems
- -- ---------------
- local function listItems()
- while true do
- print([[autoCraft ~ [list items]
- n : [n]ext page
- p : [p]revious page
- b : [b]ack to main menu
- x : e[x]it]])
- term.write("input number and hit enter key.>")
- input = read()
- if nil ~= string.find("/u/b/x/", "/" .. input .. "/") then
- return input
- else
- print("wrong input.")
- end
- end
- end
- -- ---------------
- -- isChest
- -- ---------------
- local function isChest(inspectFunction)
- rslt, data = inspectFunction()
- if nil == data then
- return false
- end
- if "minecraft:chest" == data.name or "minecraft:trapped_chest" == data.name then
- return true
- else
- return false
- end
- end
- -- =======================================================
- -- main
- -- =======================================================
- --if false == (isChest(turtle.inspect) and isChest(turtle.inspectDown)) then
- -- error("place chests (front and bottom).")
- --end
- the_db = loadData()
- if nil == the_db then
- the_db = { }
- end
- ingredientsList = { }
- promptMainMenu(the_db, ingredientsList)
- saveData(the_db)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement