Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Logistics Drone
- -- DESCRIPTION:
- -- When the user has created a suitable storage setup, this program will provide an interface for storage of as many types of items as allowed by the capacity of that storage setup.
- -- Once items are stored, the user can define templates that the logistics drone turtle (assuming it is equipped with a crafting table) can use to craft the desired items, with no user intervention.
- -- Crafting is likely going to be slower with this program than dedicated crafting machines provided by other mods, but the upside of the program is that it requires much less brain power than mod crafting machines to set up.
- -- IMPORTANT NOTE:
- -- To anyone stumbling on this program, it isn't anywhere near complete yet. If you're interested in this program, check it out later, I might create a detailed guide on how to use it when it's done.
- -- pastebin get CC2ey4Gi LDrone
- local argv = {...}
- local LOGISTICS_DATA = "logistics_data"
- local ITEM_MANIFEST = "manifest"
- local TEMPLATES_DATA = "templates"
- local RED_WOOL = "minecraft:wool"
- local YELLOW_WOOL = "minecraft:wool"
- local mode_arg = argv[1] -- "map" or "store" or "get" or "template" or "craft"
- local drone_level = 1
- local drone_column = 0
- local drone_row = 0
- local function parse_row_contents(rowFilePath)
- local rfh = fs.open(rowFilePath, "r")
- local rtn = {}
- rtn[1] = {}
- rtn[1]["name"] = rfh.readLine()
- rtn[1]["count"] = rfh.readLine()
- rtn[2] = {}
- rtn[2]["name"] = rfh.readLine()
- rtn[2]["count"] = rfh.readLine()
- rfh.close()
- return rtn
- end
- local function new_location(level, column, row, chest)
- local rtn = {}
- rtn["level"] = tonumber(level)
- rtn["column"] = tonumber(column)
- rtn["row"] = tonumber(row)
- rtn["chest"] = tonumber(chest)
- return rtn
- end
- local function get_next_free_storage()
- local levels = fs.list(LOGISTICS_DATA)
- for _, level_num in ipairs(levels) do
- local columns = fs.list(LOGISTICS_DATA .. "/" .. level_num)
- for _, column_num in ipairs(columns) do
- local rows = fs.list(LOGISTICS_DATA .. "/" .. level_num .. "/" .. column_num)
- for _, row_file in ipairs(rows) do
- local row_contents = parse_row_contents(LOGISTICS_DATA .. "/" .. level_num .. "/" .. column_num .. "/" .. row_file)
- for c=1, 2 do
- if row_contents[c]["name"] == "none" then
- return new_location(level_num, column_num, row_file, c)
- end
- end
- end
- end
- end
- return false
- end
- local function get_storage(location)
- return parse_row_contents(LOGISTICS_DATA .. "/" .. location["level"] .. "/" .. location["column"] .. "/" .. location["row"])
- end
- local function update_storage(location, new_amount, new_item)
- local row_contents = parse_row_contents(LOGISTICS_DATA .. "/" .. location["level"] .. "/" .. location["column"] .. "/" .. location["row"])
- local row_handle = fs.open(LOGISTICS_DATA .. "/" .. location["level"] .. "/" .. location["column"] .. "/" .. location["row"], "w")
- if new_item then
- row_contents[location["chest"]]["name"] = new_item
- end
- row_contents[location["chest"]]["count"] = new_amount
- for c=1, 2 do
- row_handle.writeLine(row_contents[c]["name"])
- row_handle.writeLine(row_contents[c]["count"])
- end
- row_handle.close()
- end
- local function check_manifest(for_item, itemIsFile)
- local m_file = ITEM_MANIFEST .. "/" .. for_item .. ".txt"
- if itemIsFile then
- m_file = for_item
- end
- if fs.exists(m_file) then
- local m_handle = fs.open(m_file, "r")
- local rtn = new_location(m_handle.readLine(), m_handle.readLine(), m_handle.readLine(), m_handle.readLine())
- m_handle.close()
- return rtn
- else
- return false
- end
- end
- local function new_manifest_item(new_item)
- local m_file = ITEM_MANIFEST .. "/" .. new_item .. ".txt"
- if fs.exists(m_file) then
- fs.delete(m_file)
- end
- local m_handle = fs.open(m_file, "w")
- local nfs = get_next_free_storage()
- m_handle.writeLine(tostring(nfs["level"]))
- m_handle.writeLine(tostring(nfs["column"]))
- m_handle.writeLine(tostring(nfs["row"]))
- m_handle.writeLine(tostring(nfs["chest"]))
- m_handle.close()
- update_storage(nfs, 0, new_item)
- return check_manifest(new_item)
- end
- local function check_fuel()
- if turtle.getFuelLevel() < 80 then
- turtle.select(1)
- turtle.refuel(1)
- end
- end
- local function enter_storage()
- while true do
- check_fuel()
- if not turtle.forward() then
- break
- end
- end
- end
- local function detect_below(item_name)
- if turtle.detectDown() then
- local success, data = turtle.inspectDown()
- return data.name == item_name
- end
- return false
- end
- local function detect_forward(item_name)
- local sucess, data = turtle.inspect()
- local forwardBlock = data.name
- return forwardBlock == item_name
- end
- local function level_folder(level)
- return LOGISTICS_DATA .. "/" .. tostring(level)
- end
- local function column_folder(level, column)
- return level_folder(level) .. "/" .. tostring(column)
- end
- local function row_file(level, column, row)
- return column_folder(level, column) .. "/" .. tostring(row)
- end
- local function create_level(level)
- fs.makeDir(level_folder(level))
- end
- local function create_column(level, column)
- fs.makeDir(column_folder(level, column))
- end
- local function create_row(level, column, row)
- local new_row = "none\n0\nnone\n0"
- local new_row_file = fs.open(row_file(level, column, row), "w")
- new_row_file.write(new_row)
- new_row_file.close()
- end
- local function map_rows()
- create_column(drone_level, drone_column)
- drone_row = 0
- local dist = 1
- check_fuel()
- while turtle.forward() do
- check_fuel()
- dist = dist + 1
- if dist % 2 == 0 then
- drone_row = drone_row + 1
- create_row(drone_level, drone_column, drone_row)
- end
- end
- while dist > 1 do
- check_fuel()
- turtle.back()
- dist = dist - 1
- end
- turtle.turnRight()
- turtle.forward()
- end
- local function map_columns()
- create_level(drone_level)
- drone_column = 0
- check_fuel()
- turtle.turnRight()
- while not turtle.detect() do
- while not detect_below(YELLOW_WOOL) do
- check_fuel()
- turtle.forward()
- end
- drone_column = drone_column + 1
- check_fuel()
- turtle.turnLeft()
- map_rows()
- end
- check_fuel()
- turtle.turnLeft()
- turtle.turnLeft()
- while not turtle.detect() do
- check_fuel()
- turtle.forward()
- end
- turtle.turnRight()
- end
- local function do_map()
- if fs.exists(LOGISTICS_DATA) then
- fs.delete(LOGISTICS_DATA)
- fs.makeDir(LOGISTICS_DATA)
- end
- enter_storage()
- map_columns()
- check_fuel()
- while turtle.up() do
- check_fuel()
- if turtle.detect() then
- if detect_forward(RED_WOOL) then
- drone_level = drone_level + 1
- map_columns()
- end
- end
- end
- while true do
- check_fuel()
- if not turtle.down() then
- break
- end
- end
- while true do
- check_fuel()
- if not turtle.back() then
- break
- end
- end
- end
- local function navigate_to_location(location)
- enter_storage()
- while drone_level < location["level"] do
- check_fuel()
- turtle.up()
- if detect_forward(RED_WOOL) then
- drone_level = drone_level + 1
- end
- end
- turtle.turnRight()
- while drone_column < location["column"] do
- check_fuel()
- turtle.forward()
- if detect_below(YELLOW_WOOL) then
- drone_column = drone_column + 1
- end
- end
- turtle.turnLeft()
- local dist = 1
- while drone_row < location["row"] do
- check_fuel()
- turtle.forward()
- dist = dist + 1
- if dist % 2 == 0 then
- drone_row = drone_row + 1
- end
- end
- if location["chest"] == 1 then
- turtle.turnLeft()
- else
- turtle.turnRight()
- end
- end
- local function navigate_within_storage(from_location, to_new_location)
- if from_location["chest"] == 1 then
- turtle.turnRight()
- else
- turtle.turnLeft()
- end
- local dist = from_location["row"] * 2
- while dist > 1 do
- check_fuel()
- turtle.back()
- dist = dist - 1
- end
- drone_row = 0
- if not (drone_level == to_new_location["level"]) then
- turtle.turnLeft()
- repeat
- check_fuel()
- until not turtle.forward()
- drone_column = 0
- turtle.turnRight()
- while not (drone_level == to_new_location["level"]) do
- local less_than = drone_level < to_new_location["level"]
- check_fuel()
- if less_than then
- turtle.up()
- else
- turtle.down()
- end
- if detect_forward(RED_WOOL) then
- if less_than then
- drone_level = drone_level + 1
- else
- drone_level = drone_level - 1
- end
- end
- end
- end
- turtle.turnRight()
- while drone_column < to_new_location["column"] do
- check_fuel()
- turtle.forward()
- if detect_below(YELLOW_WOOL) then
- drone_column = drone_column + 1
- end
- end
- while drone_column > to_new_location["column"] do
- check_fuel()
- turtle.back()
- if detect_below(YELLOW_WOOL) then
- drone_column = drone_column - 1
- end
- end
- turtle.turnLeft()
- dist = 1
- while drone_row < to_new_location["row"] do
- check_fuel()
- turtle.forward()
- dist = dist + 1
- if dist % 2 == 0 then
- drone_row = drone_row + 1
- end
- end
- if to_new_location["chest"] == 1 then
- turtle.turnLeft()
- else
- turtle.turnRight()
- end
- end
- local function navigate_to_start(from_location)
- if from_location["chest"] == 1 then
- turtle.turnRight()
- else
- turtle.turnLeft()
- end
- local dist = from_location["row"] * 2
- while dist > 1 do
- check_fuel()
- turtle.back()
- dist = dist - 1
- end
- turtle.turnLeft()
- while true do
- check_fuel()
- if not turtle.forward() then
- break
- end
- end
- turtle.turnRight()
- while true do
- check_fuel()
- if not turtle.down() then
- break
- end
- end
- while true do
- check_fuel()
- if not turtle.back() then
- break
- end
- end
- end
- local function store_next_item()
- drone_level = 1
- drone_column = 0
- drone_row = 0
- check_fuel()
- turtle.turnLeft()
- turtle.turnLeft()
- turtle.select(2)
- if not turtle.suck() then
- turtle.turnLeft()
- turtle.turnLeft()
- return false
- end
- local itemData = turtle.getItemDetail()
- local m_data = check_manifest(itemData.name)
- if not m_data then
- m_data = new_manifest_item(itemData.name)
- end
- turtle.turnLeft()
- turtle.turnLeft()
- navigate_to_location(m_data)
- update_storage(m_data, get_storage(m_data)[m_data["chest"]]["count"] + itemData.count)
- turtle.drop()
- navigate_to_start(m_data)
- return true
- end
- local function do_store()
- while true do
- if not store_next_item() then
- break
- end
- end
- end
- local function do_get()
- local get_amount = tonumber(argv[2])
- local items_array = {}
- local manifest_files = fs.list(ITEM_MANIFEST)
- for _, mf in ipairs(manifest_files) do
- items_array[#items_array+1] = mf
- end
- local o = 1
- while true do
- term.clear()
- term.setCursorPos(1, 1)
- for i=1, #items_array do
- if i == o then
- print("> " .. items_array[i])
- else
- print(items_array[i])
- end
- end
- local _, key = os.pullEvent("key")
- if key == keys.up and o > 1 then
- o = o - 1
- elseif key == keys.down and o < #items_array then
- o = o + 1
- elseif key == keys.enter then
- break
- end
- end
- term.clear()
- local retrieved_items = 0
- local item_location = check_manifest(ITEM_MANIFEST .. "/" .. items_array[o], true)
- while true do
- drone_level = 1
- drone_column = 0
- drone_row = 0
- enter_storage()
- navigate_to_location(item_location)
- turtle.select(2)
- if turtle.suck() then
- local sucked_items = turtle.getItemCount()
- local desired_sucked_items = get_amount - retrieved_items
- retrieved_items = retrieved_items + sucked_items
- if retrieved_items > get_amount then
- turtle.drop(retrieved_items - get_amount)
- sucked_items = desired_sucked_items
- end
- update_storage(item_location, get_storage(item_location)[item_location["chest"]]["count"] - sucked_items)
- navigate_to_start(item_location)
- turtle.turnLeft()
- turtle.turnLeft()
- turtle.select(2)
- turtle.drop()
- turtle.turnRight()
- turtle.turnRight()
- else
- navigate_to_start(item_location)
- break
- end
- if retrieved_items >= get_amount then
- break
- end
- end
- end
- local function template_creator()
- local template_name = argv[2]
- local items_array = {"none"}
- local manifest_files = fs.list(ITEM_MANIFEST)
- for _, mf in ipairs(manifest_files) do
- items_array[#items_array+1] = mf
- end
- local template_raw = ""
- local o = 1
- local curr_space = 1
- while curr_space <= 9 do
- term.clear()
- term.setCursorPos(1, 1)
- for i=1, #items_array do
- if i == o then
- print("> " .. items_array[i])
- elseif math.abs(i - o) < 3 then
- print(items_array[i])
- elseif math.abs(i - o) == 3 then
- print("...")
- end
- end
- print("")
- for g=0, 2 do
- local grid_line = ""
- for gs=1, 3 do
- local actual_space = (g * 3) + gs
- if actual_space == curr_space then
- grid_line = grid_line .. "X"
- elseif actual_space < curr_space then
- grid_line = grid_line .. "0"
- else
- grid_line = grid_line .. "O"
- end
- end
- print(grid_line)
- end
- local _, key = os.pullEvent("key")
- if key == keys.up and o > 1 then
- o = o - 1
- elseif key == keys.down and o < #items_array then
- o = o + 1
- elseif key == keys.enter then
- template_raw = template_raw .. items_array[o] .. "\n"
- curr_space = curr_space + 1
- end
- end
- term.clear()
- local th = fs.open(TEMPLATES_DATA .. "/" .. template_name, "w")
- th.write(template_raw)
- th.close()
- print("Crafting Template " .. template_name .. " successfully created!")
- end
- local function select_craft_slot(craft_slot)
- if craft_slot <= 3 then
- turtle.select(craft_slot + 5)
- elseif craft_slot <= 6 then
- turtle.select(craft_slot + 6)
- elseif craft_slot <= 9 then
- turtle.select(craft_slot + 7)
- end
- end
- local function do_craft()
- local craft_amount = tonumber(argv[2])
- local templates_array = {}
- local template_files = fs.list(TEMPLATES_DATA)
- for _, tf in ipairs(template_files) do
- templates_array[#templates_array+1] = tf
- end
- local o = 1
- while true do
- term.clear()
- term.setCursorPos(1, 1)
- for i=1, #templates_array do
- if i == o then
- print("> " .. templates_array[i])
- else
- print(templates_array[i])
- end
- end
- local _, key = os.pullEvent("key")
- if key == keys.up and o > 1 then
- o = o - 1
- elseif key == keys.down and o < #templates_array then
- o = o + 1
- elseif key == keys.enter then
- break
- end
- end
- term.clear()
- local template_items = {}
- local individual_items = {}
- local individual_items_map = {}
- local template_h = fs.open(TEMPLATES_DATA .. "/" .. template_files[o], "r")
- for s=1, 9 do
- local item_file = template_h.readLine()
- template_items[s] = item_file
- if not individual_items_map[item_file] then
- individual_items[#individual_items+1] = item_file
- individual_items_map[item_file] = true
- end
- end
- template_h.close()
- local last_item_location = nil
- local current_item = 1
- while current_item <= #individual_items do
- if not (individual_items[current_item] == "none") then
- local item_location = check_manifest(ITEM_MANIFEST .. "/" .. individual_items[current_item], true)
- if not last_item_location then
- drone_level = 1
- drone_column = 0
- drone_row = 0
- enter_storage()
- navigate_to_location(item_location)
- else
- navigate_within_storage(last_item_location, item_location)
- end
- for s=1, 9 do
- if template_items[s] == individual_items[current_item] then
- select_craft_slot(s)
- turtle.suck(craft_amount)
- update_storage(item_location, get_storage(item_location)[item_location["chest"]]["count"] - turtle.getItemCount())
- end
- end
- if current_item == #individual_items then
- navigate_to_start(item_location)
- end
- last_item_location = item_location
- end
- current_item = current_item + 1
- end
- turtle.turnLeft()
- turtle.turnLeft()
- turtle.select(1)
- turtle.dropUp()
- local current_crafted_items = 0
- while current_crafted_items < craft_amount do
- turtle.craft()
- current_crafted_items = current_crafted_items + turtle.getItemCount()
- turtle.drop()
- end
- turtle.suckUp()
- turtle.turnRight()
- turtle.turnRight()
- end
- if mode_arg == "map" then
- do_map()
- elseif mode_arg == "store" then
- do_store()
- elseif mode_arg == "get" then
- do_get()
- elseif mode_arg == "template" then
- template_creator()
- elseif mode_arg == "craft" then
- do_craft()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement