if fs.exists(file.to) and file.overwrite then
local tmp = textutils.serialize(math.random(100000,999999))
local ok = shell.run("wget "..url.." "..tmp)
- if ok then
+ if ok then -- not working?
print("Overwriting "..file.to)
fs.delete(file.to)
- fs.move(tmp,file.to)
+-- fs.move(tmp,file.to) -- fails with no such file
+ shell.run("mv "..tmp.." "..file.to) -- workaround
end
else
shell.run("wget "..url.." "..file.to)
--- /dev/null
+local t = {}
+
+-- index: find items in inventories
+-- inventory_address: string
+-- items: list of strings or nil/false. if nil/false, indexes all items.
+-- returns a table that maps item names to { amount = 0, slots = {} } where
+-- amount is the total amount of the item in the inventory and slots is a
+-- table where the keys are slot numbers and the values are how many items
+-- are in the slot.
+t.index = function(inventory_address, items)
+ local inventory = peripheral.wrap(inventory_address)
+ local slots = inventory.list()
+ local index = {}
+
+ local should_index = {}
+ if items then
+ for _, name in pairs(items) do
+ should_index[name] = true
+ end
+ end
+
+ for slot, item in pairs(slots) do
+ if not items or (item.name and should_index[item.name]) then
+ index[item.name] = index[item.name] or { amount = 0, slots = {} }
+ index[item.name].amount = index[item.name].amount + item.count
+ index[item.name].slots[slot] = item.count
+ end
+ end
+ return index
+end
+
+-- find: similar to index, but stops indexing once the required amount of each
+-- item is found.
+-- inventory_address: string
+-- item_amounts: a table that maps item names to amounts
+-- returns bool, table where table maps item names to { amount = 0, slots = {} }
+-- much like the index function, but where the amounts are less than or equal
+-- to the amounts provided in item_amounts and slots is a table where the keys
+-- are slot numbers end values are how many items "was found" in the slot. bool
+-- is whether all the items in item_amounts were found or not.
+t.find = function(inventory_address, item_amounts)
+ local inventory = peripheral.wrap(inventory_address)
+ local slots = inventory.list()
+
+ local missing = {}
+ for name, amount in pairs(item_amounts) do
+ missing[name].amount = amount
+ end
+
+ local index = {}
+ local found_all = false
+ for slot, item in pairs(slots) do
+ if missing == {} then
+ found_all = true
+ break
+ end
+ if item.name and missing[item.name] then
+ index[item.name] = index[item.name] or { amount = 0, slots = {} }
+ if item.count < missing[item.name] then
+ index[item.name].amount = index[item.name].amount + item.count
+ index[item.name].slots[slot] = item.count
+ missing[item.name] = missing[item.name] - item.count
+ else
+ index[item.name].amount = index[item.name].amount + missing[item.name]
+ index[item.name].slots[slot] = missing[item.name]
+ missing[item.name] = nil
+ end
+ end
+ end
+ return found_all, index
+end
+
+-- move: tries to move items from one inventory to another
+-- source_address: string
+-- destination_address: string
+-- item_amounts: a table that maps item names to amounts
+-- returns true on success and false, string on fail
+t.move = function(source_address, destination_address, item_amounts)
+ local source_inventory = peripheral.wrap(source_address)
+ local ok, index = t.find(source_address, item_amounts)
+ local err = false
+ if not ok then
+ err = "not enough items"
+ else
+ for item_name, slots in pairs(index) do
+ for slot, amount in pairs(slots) do
+ source_inventory.pushItems(destination_address, slot, amount)
+ -- todo: pushItems may fail
+ end
+ end
+ end
+ return not err or table.unpack({ false, "Could not move: "..err })
+end
+
+
+
+return t
+++ /dev/null
--- turtle-utils.lua
---
--- depends on:
--- oneOf
---
--- implements:
--- findItem : list of item names -> index | false message
--- findEmpty : index | false message
--- count : list of item names -> count
--- selectItem : list of item names -> true | false message
--- transferAndSelect : index -> list of items -> true | false message
--- movementMap : t f
--- runStringCommand : string -> true | false message
--- rep : number of repeats -> string -> string | nil
-
---------------------------------------- for now
--- t a -> a -> bool
--- returns whether a is found in t
-local oneOf = function(t, a)
- for _,b in pairs(t) do
- if b == a then return true end
- end
- return false
-end
---------------------------------------
-
-local lib = {}
-
--- findItem : list of item names -> index | false message
--- returns the first inventory index containing an item from list t
--- if no item is found, returns nil
-lib.findItem = function(t)
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if item and oneOf(t, item.name) then return i end
- end
- return false, "Item(s) not found"
-end
-
--- findEmpty : index | false message
--- returns the first empty slot
--- if no empty slot is found, returns nil
-lib.findEmpty = function()
- for i = 1, 16 do if not turtle.getItemDetail(i) then return i end end
- return false, "No empty slot"
-end
-
--- count : list of item names -> count
--- counts how many slots contain an item from list t
--- (does not count individual items)
-lib.count = function(t)
- local c = 0
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if item and oneOf(t, item.name) then
- c = c + 1
- break
- end
- end
-end
-
--- selectItem : list of item names -> true | false message
--- select first slot containing an item from list t if not already selected.
--- returns bool.
-lib.selectItem = function(t)
- local item = turtle.getItemDetail()
- if item and oneOf(t, item.name) then
- return true
- else
- local i, e = find(t)
- if i then
- turtle.select(i)
- return true
- end
- end
- return false, "Nothing to select: " .. e
-end
-
--- transferAndSelect : index -> list of items -> true | false message
--- like selectItem, selects item from list, but tries to move it to the first slot.
--- requires an empty slot to move items around.
--- (this function exists because weak automata cannot digBlock with tools in slots >9)
-lib.transferAndSelect = function(i, t)
- if i < 1 or i > 16 then return false, msg .. "Index out of range" end
- -- if a wanted item already is in the wanted slot, select it and return early
- local item = turtle.getItemDetail(i)
- if item and oneOf(t, item.name) then
- turtle.select(i)
- return true
- end
- local msg = "Could not transfer and select: "
- local i_tmp, e = lib.findEmpty()
- if not i_tmp then return false, msg .. e end
- local i_from, e = lib.findItem(t)
- if not i_from then return false, msg .. e end
- -- if the i'th slot is free, skip the unnecessary item shuffle
- if not turtle.getItemDetail(i) then
- turtle.select(i_from)
- turtle.transferTo(i)
- else
- turtle.select(i)
- turtle.transferTo(i_tmp)
- turtle.select(i_from)
- turtle.transferTo(i)
--- turtle.select(i_tmp)
--- turtle.transferTo(i_from)
- end
- turtle.select(i)
- return true
-end
-
-
--- commands as strings
--- chars corresponds to actions, when immediatel followed by a number, repeats the action that many times
--- "udfblrh" = up -> down -> forward -> backward -> turn left -> turn right -> harvest
--- "u15r" = 15x up -> turn right
--- "u15 r" = 15x up -> turn right
--- "u1 5r" = invalid
-
--- movementMap : t f
-lib.movementMap =
- { ["u"] = turtle.up
- , ["d"] = turtle.down
- , ["f"] = turtle.forward
- , ["b"] = turtle.back
- , ["l"] = turtle.turnLeft
- , ["r"] = turtle.turnRight
- }
-
--- runStringCommand : string -> true | false message
-lib.runStringCommand = function(str, map)
- local c, n, rest = string.match(string.gsub(str, "^%s+", ""), "^(%w)(%d*)(.*)")
- if not c then return true end
- if n == "" then n = 1 else n = tonumber(n) end
- for i = 1, n do map[c]() end
--- print(cmd, tostring(i).."/"..tostring(n))
--- end
- return lib.runStringCommand(rest, map)
-end
-
--- rep : number of repeats -> string -> string | nil
--- repeats string n times
-lib.rep = function(n, str)
- if not n or n < 0 then return nil end
- local s = ""
- for i = 1, n do
- s = s .. str
- end
- return s
-end
-
-return lib
--- /dev/null
+-- turtle-utils.lua
+--
+-- depends on:
+-- oneOf
+--
+-- implements:
+-- findItem : list of item names -> index | false message
+-- findEmpty : index | false message
+-- count : list of item names -> count
+-- selectItem : list of item names -> true | false message
+-- transferAndSelect : index -> list of items -> true | false message
+-- movementMap : t f
+-- runStringCommand : string -> true | false message
+-- rep : number of repeats -> string -> string | nil
+
+--------------------------------------- for now
+-- t a -> a -> bool
+-- returns whether a is found in t
+local oneOf = function(t, a)
+ for _,b in pairs(t) do
+ if b == a then return true end
+ end
+ return false
+end
+--------------------------------------
+
+local lib = {}
+
+-- findItem : list of item names -> index | false message
+-- returns the first inventory index containing an item from list t
+-- if no item is found, returns nil
+lib.findItem = function(t)
+ for i = 1, 16 do
+ local item = turtle.getItemDetail(i)
+ if item and oneOf(t, item.name) then return i end
+ end
+ return false, "Item(s) not found"
+end
+
+-- findEmpty : index | false message
+-- returns the first empty slot
+-- if no empty slot is found, returns nil
+lib.findEmpty = function()
+ for i = 1, 16 do if not turtle.getItemDetail(i) then return i end end
+ return false, "No empty slot"
+end
+
+-- count : list of item names -> count
+-- counts how many slots contain an item from list t
+-- (does not count individual items)
+lib.count = function(t)
+ local c = 0
+ for i = 1, 16 do
+ local item = turtle.getItemDetail(i)
+ if item and oneOf(t, item.name) then
+ c = c + 1
+ break
+ end
+ end
+end
+
+-- selectItem : list of item names -> true | false message
+-- select first slot containing an item from list t if not already selected.
+-- returns bool.
+lib.selectItem = function(t)
+ local item = turtle.getItemDetail()
+ if item and oneOf(t, item.name) then
+ return true
+ else
+ local i, e = find(t)
+ if i then
+ turtle.select(i)
+ return true
+ end
+ end
+ return false, "Nothing to select: " .. e
+end
+
+-- transferAndSelect : index -> list of items -> true | false message
+-- like selectItem, selects item from list, but tries to move it to the first slot.
+-- requires an empty slot to move items around.
+-- (this function exists because weak automata cannot digBlock with tools in slots >9)
+lib.transferAndSelect = function(i, t)
+ if i < 1 or i > 16 then return false, msg .. "Index out of range" end
+ -- if a wanted item already is in the wanted slot, select it and return early
+ local item = turtle.getItemDetail(i)
+ if item and oneOf(t, item.name) then
+ turtle.select(i)
+ return true
+ end
+ local msg = "Could not transfer and select: "
+ local i_tmp, e = lib.findEmpty()
+ if not i_tmp then return false, msg .. e end
+ local i_from, e = lib.findItem(t)
+ if not i_from then return false, msg .. e end
+ -- if the i'th slot is free, skip the unnecessary item shuffle
+ if not turtle.getItemDetail(i) then
+ turtle.select(i_from)
+ turtle.transferTo(i)
+ else
+ turtle.select(i)
+ turtle.transferTo(i_tmp)
+ turtle.select(i_from)
+ turtle.transferTo(i)
+-- turtle.select(i_tmp)
+-- turtle.transferTo(i_from)
+ end
+ turtle.select(i)
+ return true
+end
+
+
+-- commands as strings
+-- chars corresponds to actions, when immediatel followed by a number, repeats the action that many times
+-- "udfblrh" = up -> down -> forward -> backward -> turn left -> turn right -> harvest
+-- "u15r" = 15x up -> turn right
+-- "u15 r" = 15x up -> turn right
+-- "u1 5r" = invalid
+
+-- movementMap : t f
+lib.movementMap =
+ { ["u"] = turtle.up
+ , ["d"] = turtle.down
+ , ["f"] = turtle.forward
+ , ["b"] = turtle.back
+ , ["l"] = turtle.turnLeft
+ , ["r"] = turtle.turnRight
+ }
+
+-- runStringCommand : string -> true | false message
+lib.runStringCommand = function(str, map)
+ local c, n, rest = string.match(string.gsub(str, "^%s+", ""), "^(%w)(%d*)(.*)")
+ if not c then return true end
+ if n == "" then n = 1 else n = tonumber(n) end
+ for i = 1, n do map[c]() end
+-- print(cmd, tostring(i).."/"..tostring(n))
+-- end
+ return lib.runStringCommand(rest, map)
+end
+
+-- rep : number of repeats -> string -> string | nil
+-- repeats string n times
+lib.rep = function(n, str)
+ if not n or n < 0 then return nil end
+ local s = ""
+ for i = 1, n do
+ s = s .. str
+ end
+ return s
+end
+
+return lib
-cc lib/turtle-utils.lua:/lib/turtle-utils.lua:o
+cc lib/turtle.lua:/lib/turtle.lua:o
+cc lib/inventory.lua:/lib/inventory.lua:o
cc vineyard/turtle/harvest.lua:/bin/harvest.lua:o