Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function save(tbl, name)
- local file = fs.open(name, "w")
- file.write(textutils.serialize(tbl))
- file.close()
- end
- function load(name)
- local file = fs.open(name, "r")
- if not file then
- if name == "open_positions" then
- save({{x=-5,y=3,z=-5,side="down"}}, name)
- else
- save({}, name)
- end
- return load(name)
- else
- local data = file.readAll()
- file.close()
- return textutils.unserialize(data)
- end
- end
- function go_to(target)
- if me.y ~= target.y then
- go_to({x = 0, y = me.y, z = 0})
- while me.y < target.y do
- if turtle.up() then me.y = me.y + 1 end
- end
- while me.y > target.y do
- if turtle.down() then me.y = me.y - 1 end
- end
- end
- if me.x < target.x then
- turtle.turnRight()
- while me.x < target.x do
- if turtle.forward() then me.x = me.x + 1 end
- end
- turtle.turnLeft()
- end
- if me.x > target.x then
- turtle.turnLeft()
- while me.x > target.x do
- if turtle.forward() then me.x = me.x - 1 end
- end
- turtle.turnRight()
- end
- while me.z < target.z do
- if turtle.forward() then me.z = me.z + 1 end
- end
- while me.z > target.z do
- if turtle.back() then me.z = me.z - 1 end
- end
- end
- function next_position(position)
- local new_position = {x = position.x, y = position.y, z = position.z, side = position.side}
- if position.side == "down" then
- new_position.side = "up"
- else
- new_position.side = "down"
- if position.x == 5 then
- new_position.x = -5
- if position.z == 5 then
- new_position.z = -5
- new_position.y = position.y + 3
- else
- new_position.z = position.z + 1
- end
- else
- if position.x == -1 and position.z == 0 then
- new_position.x = position.x + 2
- else
- new_position.x = position.x + 1
- end
- end
- end
- return new_position
- end
- function get_enderchest(group)
- turtle.select(16)
- turtle.placeDown()
- turtle.select(1)
- end
- function safe_string(text)
- local new_text = {}
- for i = 1, #text do
- local val = string.byte(text, i)
- new_text[i] = (val > 31 and val < 127) and val or 32
- end
- return string.char(unpack(new_text))
- end
- function earliest_order(position_1, position_2)
- if position_1.y > position_2.y then
- return true
- elseif position_1.y == position_2.y then
- if position_1.z > position_2.z then
- return true
- elseif position_1.z == position_2.z then
- if position_1.x > position_2.x then
- return true
- elseif position_1.x == position_2.x then
- if position_1.side == "up" then
- return true
- end
- end
- end
- end
- end
- function next_open_position()
- if #open_positions > 1 then
- table.sort(open_positions, earliest_order)
- return table.remove(open_positions)
- else
- local position = table.remove(open_positions)
- table.insert(open_positions, next_position(position))
- return position
- end
- end
- function register(stack)
- local item = nil
- stack.string_id = safe_string(stack.id..stack.dmg..stack.raw_name..stack.display_name)
- for _, existing_item in ipairs(items) do
- if existing_item.string_id == stack.string_id then
- item = existing_item
- break
- end
- end
- if not item then
- item = {}
- item.string_id = stack.string_id
- item.damage = stack.dmg
- item.max_damage = stack.max_dmg
- item.max_stack = stack.max_size
- item.recipes = {}
- item.quantity = 0
- item.position = next_open_position()
- item.slot = {}
- item.display_name = stack.display_name
- table.insert(items, item)
- end
- if item.position == nil then
- item.position = next_open_position()
- end
- save(open_positions, "open_positions")
- return item
- end
- function condense_inventory()
- inventory.condenseItems()
- local inventory_items = inventory.getAllStacks()
- inventory.swapStacks(#inventory_items, 16)
- return inventory_items
- end
- function check_inventory()
- local items_to_sort = {}
- local inventory_items = condense_inventory()
- for i = 1, #inventory_items - 1 do
- table.insert(items_to_sort, register(inventory_items[i].basic()))
- end
- return items_to_sort
- end
- function distance_away(position)
- local distance = math.abs(position.y - me.y)
- distance = distance + math.abs(me.x) + math.abs(me.z)
- distance = distance + math.abs(position.x) + math.abs(position.z)
- return distance
- end
- function closest_order(item_1, item_2)
- return distance_away(item_1.position) > distance_away(item_2.position)
- end
- function give_item_slots(items_to_sort)
- for i = 1, #items_to_sort do
- table.insert(items_to_sort[i].slot, i)
- end
- end
- function deposit_item(item)
- go_to(item.position)
- for _, slot_number in ipairs(item.slot) do
- local amount = inventory.pushItem(item.position.side, slot_number)
- item.quantity = item.quantity + amount
- end
- item.slot = {}
- save(items, "items")
- end
- function sort_items(items_to_sort)
- give_item_slots(items_to_sort)
- while #items_to_sort > 0 do
- table.sort(items_to_sort, closest_order)
- local closest_item = items_to_sort[#items_to_sort]
- deposit_item(closest_item)
- table.remove(items_to_sort)
- end
- end
- function begin_depositing()
- go_to({x=0, y=me.y, z=0})
- local at_home = turtle.detectDown()
- condense_inventory()
- if not at_home then
- get_enderchest("deposit")
- end
- while turtle.suckDown() do end
- if not at_home then
- if inventory.getStackInSlot(16) then
- inventory.pushItem("down", 16)
- end
- end
- chest.condenseItems()
- if #chest.getAllStacks() > 0 then
- table.insert(queue, 2, {begin_depositing})
- end
- if not at_home then
- turtle.select(16)
- turtle.digDown()
- end
- local items_to_sort = check_inventory()
- sort_items(items_to_sort)
- end
- function start()
- home = {x=0,y=0,z=0}
- me = {x=home.x,y=home.y,z=home.z}
- queue = {}
- chest = peripheral.wrap("bottom")
- while not chest do
- sleep(3)
- chest = peripheral.wrap("bottom")
- end
- inventory = peripheral.wrap("left")
- items = load("items")
- open_positions = load("open_positions")
- end
- function spit()
- for i=1, 15 do
- turtle.select(i)
- turtle.drop()
- end
- end
- function fetch(item, quantity)
- if quantity > item.quantity then
- print("Too many")
- else
- go_to(item.position)
- local amount = inventory.pullItem(item.position.side, 2, quantity)
- item.quantity = item.quantity - amount
- if item.quantity == 0 then
- table.insert(open_positions, item.position)
- save(open_positions, "open_positions")
- item.position = nil
- end
- save(items, "items")
- go_to(home)
- spit()
- end
- end
- function do_queue()
- local i = 1
- while i <= #queue do
- queue[i][1](queue[i][2],queue[i][3])
- i = i + 1
- end
- queue = {}
- go_to(home)
- end
- function search(s1, s2)
- local s1 = string.lower(string.gsub(string.gsub(s1, " ", ""), "_", ""))
- local s2 = string.lower(string.gsub(string.gsub(s2, " ", ""), "_", ""))
- return string.find(s1, s2)
- end
- function slice(tbl, first, last)
- local sliced = {}
- for i = first, last do
- table.insert(sliced, tbl[i])
- end
- return sliced
- end
- function show_results()
- term.clear()
- term.setCursorPos(1,1)
- for i, result in pairs(slice(results, 1, 12)) do
- print("#"..i.." "..result.display_name..": "..result.quantity)
- end
- term.setCursorPos(1,13)
- end
- function start_search(search_term)
- results = {}
- for _, item in ipairs(items) do
- r = search(item.display_name, search_term)
- if r and item.quantity > 0 then
- table.insert(results, item)
- end
- end
- show_results()
- end
- start()
- while true do
- command = io.read()
- if command == ">" or command == "sort" then
- table.insert(queue, {begin_depositing})
- elseif command == "" then
- do_queue()
- elseif tonumber(command) and #results > 0 and tonumber(command) <= #results then
- n = tonumber(command)
- print(results[n].display_name..": "..results[n].quantity)
- print("How many?")
- amount = io.read()
- while not tonumber(amount) or amount == "x" do
- amount = io.read()
- end
- if amount == "x" then
- show_results()
- else
- table.insert(queue, {fetch, results[n], tonumber(amount)})
- end
- else
- start_search(command)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement