1
0
mirror of https://github.com/kepler155c/opus synced 2024-06-18 19:30:01 +00:00

spaces->tabs + cleanup + pathing fixes

This commit is contained in:
kepler155c@gmail.com 2019-06-18 15:19:24 -04:00
parent 82ec4db50f
commit 3c22a872b0
37 changed files with 1948 additions and 1703 deletions

View File

@ -1,61 +0,0 @@
--[[
Mount a readonly file system from another computer across rednet. The
target computer must be running OpusOS or redserver. Dissimlar to samba
in that a snapshot of the target is taken upon mounting - making this
faster.
Useful for mounting a non-changing directory tree.
Syntax:
rttp://<id>/directory/subdir
Examples:
rttp://12/usr/etc
rttp://8/usr
]]--
local rttp = require('rttp')
local fs = _G.fs
local redfs = { }
local function getListing(uri)
local success, response = rttp.get(uri .. '?recursive=true')
if not success then
error(response)
end
if response.statusCode ~= 200 then
error('Received response ' .. response.statusCode)
end
local list = { }
for _,v in pairs(response.data) do
if not v.isDir then
list[v.path] = {
url = uri .. '/' .. v.path,
size = v.size,
}
end
end
return list
end
function redfs.mount(dir, uri)
if not uri then
error('redfs syntax: uri')
end
local list = getListing(uri)
for path, entry in pairs(list) do
if not fs.exists(fs.combine(dir, path)) then
local node = fs.mount(fs.combine(dir, path), 'urlfs', entry.url)
node.size = entry.size
end
end
end
return redfs

View File

@ -1,4 +1,4 @@
local rttp = require('rttp') --local rttp = require('rttp')
local Util = require('util') local Util = require('util')
local fs = _G.fs local fs = _G.fs
@ -39,7 +39,6 @@ function urlfs.getDrive()
end end
function urlfs.open(node, fn, fl) function urlfs.open(node, fn, fl)
if fl == 'w' or fl == 'wb' then if fl == 'w' or fl == 'wb' then
fs.delete(fn) fs.delete(fn)
return fs.open(fn, fl) return fs.open(fn, fl)
@ -51,12 +50,15 @@ function urlfs.open(node, fn, fl)
local c = node.cache local c = node.cache
if not c then if not c then
--[[
if node.url:match("^(rttps?:)") then if node.url:match("^(rttps?:)") then
local s, response = rttp.get(node.url) local s, response = rttp.get(node.url)
c = s and response.statusCode == 200 and response.data c = s and response.statusCode == 200 and response.data
else else
c = Util.httpGet(node.url) c = Util.httpGet(node.url)
end end
]]--
c = Util.httpGet(node.url)
if c then if c then
node.cache = c node.cache = c
node.size = #c node.size = #c

View File

@ -1,215 +1,584 @@
-- credit ElvishJerricco -- Module options:
-- http://pastebin.com/raw.php?i=4nRg9CHU local register_global_module_table = false
local global_module_name = 'json'
local json = { } --[==[
NOTE: Modified to reduce file size.
See https://github.com/LuaDist/dkjson/blob/master/dkjson.lua
for full version.
------------------------------------------------------------------ utils David Kolf's JSON module for Lua 5.1/5.2
local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"} Version 2.5
local function isArray(t) For the documentation see the corresponding readme.txt or visit
local max = 0 <http://dkolf.de/src/dkjson-lua.fsl/>.
for k,v in pairs(t) do
if type(k) ~= "number" then You can contact the author by sending an e-mail to 'david' at the
domain 'dkolf.de'.
Copyright (C) 2010-2014 David Heiko Kolf
Refer to license located at https://github.com/LuaDist/dkjson/blob/master/dkjson.lua
--]==]
-- global dependencies:
local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
local error, require, pcall, select = error, require, pcall, select
local floor, huge = math.floor, math.huge
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
string.rep, string.gsub, string.sub, string.byte, string.char,
string.find, string.len, string.format
local strmatch = string.match
local concat = table.concat
local json = { version = "dkjson 2.5" }
if register_global_module_table then
_G[global_module_name] = json
end
local _ENV = nil -- blocking globals in Lua 5.2
pcall (function()
-- Enable access to blocked metatables.
-- Don't worry, this module doesn't change anything in them.
local debmeta = require "debug".getmetatable
if debmeta then getmetatable = debmeta end
end)
json.null = setmetatable ({}, {
__tojson = function () return "null" end
})
local function isarray (tbl)
local max, n, arraylen = 0, 0, 0
for k,v in pairs (tbl) do
if k == 'n' and type(v) == 'number' then
arraylen = v
if v > max then
max = v
end
else
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
return false return false
elseif k > max then end
if k > max then
max = k max = k
end end
n = n + 1
end end
return max == #t end
if max > 10 and max > arraylen and max > n * 2 then
return false -- don't create an array with too many holes
end
return true, max
end end
local whites = {['\n']=true; ['\r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true} local escapecodes = {
local function removeWhite(str) ["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
while whites[str:sub(1, 1)] do ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
str = str:sub(2) }
local function escapeutf8 (uchar)
local value = escapecodes[uchar]
if value then
return value
end end
local a, b, c, d = strbyte (uchar, 1, 4)
a, b, c, d = a or 0, b or 0, c or 0, d or 0
if a <= 0x7f then
value = a
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
value = (a - 0xc0) * 0x40 + b - 0x80
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
else
return ""
end
if value <= 0xffff then
return strformat ("\\u%.4x", value)
elseif value <= 0x10ffff then
-- encode as UTF-16 surrogate pair
value = value - 0x10000
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
else
return ""
end
end
local function fsub (str, pattern, repl)
-- gsub always builds a new string in a buffer, even when no match
-- exists. First using find should be more efficient when most strings
-- don't contain the pattern.
if strfind (str, pattern) then
return gsub (str, pattern, repl)
else
return str return str
end end
------------------------------------------------------------------ encoding
local function encodeCommon(val, pretty, tabLevel, tTracking)
local str = ""
-- Tabbing util
local function tab(s)
str = str .. ("\t"):rep(tabLevel) .. s
end end
local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc) local function quotestring (value)
str = str .. bracket -- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
if pretty then value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
str = str .. "\n" if strfind (value, "[\194\216\220\225\226\239]") then
tabLevel = tabLevel + 1 value = fsub (value, "\194[\128-\159\173]", escapeutf8)
value = fsub (value, "\216[\128-\132]", escapeutf8)
value = fsub (value, "\220\143", escapeutf8)
value = fsub (value, "\225\158[\180\181]", escapeutf8)
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
value = fsub (value, "\239\187\191", escapeutf8)
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
end end
for k,v in iterator(val) do return "\"" .. value .. "\""
tab("")
loopFunc(k,v)
str = str .. ","
if pretty then str = str .. "\n" end
end
if pretty then
tabLevel = tabLevel - 1
end
if str:sub(-2) == ",\n" then
str = str:sub(1, -3) .. "\n"
elseif str:sub(-1) == "," then
str = str:sub(1, -2)
end
tab(closeBracket)
end end
json.quotestring = quotestring
-- Table encoding local function replace(str, o, n)
if type(val) == "table" then local i, j = strfind (str, o, 1, true)
assert(not tTracking[val], "Cannot encode a table holding itself recursively") if i then
tTracking[val] = true return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
if isArray(val) then
arrEncoding(val, "[", "]", ipairs, function(k,v)
str = str .. encodeCommon(v, pretty, tabLevel, tTracking)
end)
else else
arrEncoding(val, "{", "}", pairs, function(k,v)
assert(type(k) == "string", "JSON object keys must be strings", 2)
str = str .. encodeCommon(k, pretty, tabLevel, tTracking)
str = str .. (pretty and ": " or ":") .. encodeCommon(v, pretty, tabLevel, tTracking)
end)
end
-- String encoding
elseif type(val) == "string" then
str = '"' .. val:gsub("[%c\"\\]", controls) .. '"'
-- Number encoding
elseif type(val) == "number" or type(val) == "boolean" then
str = tostring(val)
else
error("JSON only supports arrays, objects, numbers, booleans, and strings", 2)
end
return str return str
end end
function json.encode(val)
return encodeCommon(val, false, 0, {})
end end
function json.encodePretty(val) -- locale independent num2str and str2num functions
return encodeCommon(val, true, 0, {}) local decpoint, numfilter
local function updatedecpoint ()
decpoint = strmatch(tostring(0.5), "([^05+])")
-- build a filter that can be used to remove group separators
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
end end
function json.encodeToFile(path, val) updatedecpoint()
local file = io.open(path, "w")
assert(file, "Unable to open file") local function num2str (num)
file:write(json.encodePretty(val)) return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
file:close()
end end
------------------------------------------------------------------ decoding local function str2num (str)
local num = tonumber(replace(str, ".", decpoint))
local decodeControls = {} if not num then
for k,v in pairs(controls) do updatedecpoint()
decodeControls[v] = k num = tonumber(replace(str, ".", decpoint))
end
return num
end end
local function parseBoolean(str) local function addnewline2 (level, buffer, buflen)
if str:sub(1, 4) == "true" then buffer[buflen+1] = "\n"
return true, removeWhite(str:sub(5)) buffer[buflen+2] = strrep (" ", level)
buflen = buflen + 2
return buflen
end
function json.addnewline (state)
if state.indent then
state.bufferlen = addnewline2 (state.level or 0,
state.buffer, state.bufferlen or #(state.buffer))
end
end
local encode2 -- forward declaration
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
local kt = type (key)
if kt ~= 'string' and kt ~= 'number' then
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
end
if prev then
buflen = buflen + 1
buffer[buflen] = ","
end
if indent then
buflen = addnewline2 (level, buffer, buflen)
end
buffer[buflen+1] = quotestring (key)
buffer[buflen+2] = ":"
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state)
end
local function appendcustom(res, buffer, state)
local buflen = state.bufferlen
if type (res) == 'string' then
buflen = buflen + 1
buffer[buflen] = res
end
return buflen
end
local function exception(reason, value, state, buffer, buflen, defaultmessage)
defaultmessage = defaultmessage or reason
local handler = state.exception
if not handler then
return nil, defaultmessage
else else
return false, removeWhite(str:sub(6)) state.bufferlen = buflen
local ret, msg = handler (reason, value, state, defaultmessage)
if not ret then return nil, msg or defaultmessage end
return appendcustom(ret, buffer, state)
end end
end end
local function parseNull(str) function json.encodeexception(reason, value, state, defaultmessage)
return nil, removeWhite(str:sub(5)) return quotestring("<" .. defaultmessage .. ">")
end end
local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true} encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state)
local function parseNumber(str) local valtype = type (value)
local i = 1 local valmeta = getmetatable (value)
while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do valmeta = type (valmeta) == 'table' and valmeta -- only tables
i = i + 1 local valtojson = valmeta and valmeta.__tojson
if valtojson then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end end
local val = tonumber(str:sub(1, i - 1)) tables[value] = true
str = removeWhite(str:sub(i)) state.bufferlen = buflen
return val, str local ret, msg = valtojson (value, state)
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
tables[value] = nil
buflen = appendcustom(ret, buffer, state)
elseif value == nil then
buflen = buflen + 1
buffer[buflen] = "null"
elseif valtype == 'number' then
local s
if value ~= value or value >= huge or -value >= huge then
-- This is the behaviour of the original JSON implementation.
s = "null"
else
s = num2str (value)
end
buflen = buflen + 1
buffer[buflen] = s
elseif valtype == 'boolean' then
buflen = buflen + 1
buffer[buflen] = value and "true" or "false"
elseif valtype == 'string' then
buflen = buflen + 1
buffer[buflen] = quotestring (value)
elseif valtype == 'table' then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
level = level + 1
local isa, n = isarray (value)
if n == 0 and valmeta and valmeta.__jsontype == 'object' then
isa = false
end
local msg
if isa then -- JSON array
buflen = buflen + 1
buffer[buflen] = "["
for i = 1, n do
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
if i < n then
buflen = buflen + 1
buffer[buflen] = ","
end
end
buflen = buflen + 1
buffer[buflen] = "]"
else -- JSON object
local prev = false
buflen = buflen + 1
buffer[buflen] = "{"
local order = valmeta and valmeta.__jsonorder or globalorder
if order then
local used = {}
n = #order
for i = 1, n do
local k = order[i]
local v = value[k]
if v then
used[k] = true
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
prev = true -- add a seperator before the next element
end
end
for k,v in pairs (value) do
if not used[k] then
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
else -- unordered
for k,v in pairs (value) do
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
if indent then
buflen = addnewline2 (level - 1, buffer, buflen)
end
buflen = buflen + 1
buffer[buflen] = "}"
end
tables[value] = nil
else
return exception ('unsupported type', value, state, buffer, buflen,
"type '" .. valtype .. "' is not supported by JSON.")
end
return buflen
end end
local function parseString(str) function json.encode (value, state)
str = str:sub(2) state = state or {}
local s = "" local oldbuffer = state.buffer
while str:sub(1,1) ~= "\"" do local buffer = oldbuffer or {}
local next = str:sub(1,1) state.buffer = buffer
str = str:sub(2) updatedecpoint()
assert(next ~= "\n", "Unclosed string") local ret, msg = encode2 (value, state.indent, state.level or 0,
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
if next == "\\" then if not ret then
local escape = str:sub(1,1) error (msg, 2)
str = str:sub(2) elseif oldbuffer == buffer then
state.bufferlen = ret
next = assert(decodeControls[next..escape], "Invalid escape character") return true
end else
state.bufferlen = nil
s = s .. next state.buffer = nil
end return concat (buffer)
return s, removeWhite(str:sub(2))
end
function json.parseArray(str)
str = removeWhite(str:sub(2))
local val = {}
local i = 1
while str:sub(1, 1) ~= "]" do
local v
v, str = json.parseValue(str)
val[i] = v
i = i + 1
str = removeWhite(str)
end
str = removeWhite(str:sub(2))
return val, str
end
function json.parseValue(str)
local fchar = str:sub(1, 1)
if fchar == "{" then
return json.parseObject(str)
elseif fchar == "[" then
return json.parseArray(str)
elseif tonumber(fchar) ~= nil or numChars[fchar] then
return parseNumber(str)
elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then
return parseBoolean(str)
elseif fchar == "\"" then
return parseString(str)
elseif str:sub(1, 4) == "null" then
return parseNull(str)
end end
end end
function json.parseMember(str) local function loc (str, where)
local k, val local line, pos, linepos = 1, 1, 0
k, str = json.parseValue(str) while true do
val, str = json.parseValue(str) pos = strfind (str, "\n", pos, true)
return k, val, str if pos and pos < where then
line = line + 1
linepos = pos
pos = pos + 1
else
break
end
end
return "line " .. line .. ", column " .. (where - linepos)
end end
function json.parseObject(str) local function unterminated (str, what, where)
str = removeWhite(str:sub(2)) return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
local val = {}
while str:sub(1, 1) ~= "}" do
local k, v
k, v, str = json.parseMember(str)
val[k] = v
str = removeWhite(str)
end
str = removeWhite(str:sub(2))
return val, str
end end
function json.decode(str) local function scanwhite (str, pos)
str = removeWhite(str) while true do
return json.parseValue(str) pos = strfind (str, "%S", pos)
if not pos then return nil end
local sub2 = strsub (str, pos, pos + 1)
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
-- UTF-8 Byte Order Mark
pos = pos + 3
elseif sub2 == "//" then
pos = strfind (str, "[\n\r]", pos + 2)
if not pos then return nil end
elseif sub2 == "/*" then
pos = strfind (str, "*/", pos + 2)
if not pos then return nil end
pos = pos + 2
else
return pos
end
end
end end
local escapechars = {
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
}
local function unichar (value)
if value < 0 then
return nil
elseif value <= 0x007f then
return strchar (value)
elseif value <= 0x07ff then
return strchar (0xc0 + floor(value/0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0xffff then
return strchar (0xe0 + floor(value/0x1000),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0x10ffff then
return strchar (0xf0 + floor(value/0x40000),
0x80 + (floor(value/0x1000) % 0x40),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
else
return nil
end
end
local function scanstring (str, pos)
local lastpos = pos + 1
local buffer, n = {}, 0
while true do
local nextpos = strfind (str, "[\"\\]", lastpos)
if not nextpos then
return unterminated (str, "string", pos)
end
if nextpos > lastpos then
n = n + 1
buffer[n] = strsub (str, lastpos, nextpos - 1)
end
if strsub (str, nextpos, nextpos) == "\"" then
lastpos = nextpos + 1
break
else
local escchar = strsub (str, nextpos + 1, nextpos + 1)
local value
if escchar == "u" then
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
if value then
local value2
if 0xD800 <= value and value <= 0xDBff then
-- we have the high surrogate of UTF-16. Check if there is a
-- low surrogate escaped nearby to combine them.
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
else
value2 = nil -- in case it was out of range for a low surrogate
end
end
end
value = value and unichar (value)
if value then
if value2 then
lastpos = nextpos + 12
else
lastpos = nextpos + 6
end
end
end
end
if not value then
value = escapechars[escchar] or escchar
lastpos = nextpos + 2
end
n = n + 1
buffer[n] = value
end
end
if n == 1 then
return buffer[1], lastpos
elseif n > 1 then
return concat (buffer), lastpos
else
return "", lastpos
end
end
local scanvalue -- forward declaration
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
local len = strlen (str)
local tbl, n = {}, 0
local pos = startpos + 1
if what == 'object' then
setmetatable (tbl, objectmeta)
else
setmetatable (tbl, arraymeta)
end
while true do
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
local char = strsub (str, pos, pos)
if char == closechar then
return tbl, pos + 1
end
local val1, err
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
if char == ":" then
if val1 == nil then
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
end
pos = scanwhite (str, pos + 1)
if not pos then return unterminated (str, what, startpos) end
local val2
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
tbl[val1] = val2
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
else
n = n + 1
tbl[n] = val1
end
if char == "," then
pos = pos + 1
end
end
end
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
pos = pos or 1
pos = scanwhite (str, pos)
if not pos then
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
end
local char = strsub (str, pos, pos)
if char == "{" then
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
elseif char == "[" then
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
elseif char == "\"" then
return scanstring (str, pos)
else
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
if pstart then
local number = str2num (strsub (str, pstart, pend))
if number then
return number, pend + 1
end
end
pstart, pend = strfind (str, "^%a%w*", pos)
if pstart then
local name = strsub (str, pstart, pend)
if name == "true" then
return true, pend + 1
elseif name == "false" then
return false, pend + 1
elseif name == "null" then
return nullval, pend + 1
end
end
return nil, pos, "no valid JSON value at " .. loc (str, pos)
end
end
local function optionalmetatables(...)
if select("#", ...) > 0 then
return ...
else
return {__jsontype = 'object'}, {__jsontype = 'array'}
end
end
function json.decode (str, pos, nullval, ...)
local objectmeta, arraymeta = optionalmetatables(...)
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
end
-- NOTE: added method - not in original source
function json.decodeFromFile(path) function json.decodeFromFile(path)
local file = assert(fs.open(path, "r")) local file = assert(fs.open(path, "r"))
local decoded = json.decode(file.readAll()) local decoded = json.decode(file.readAll())

View File

@ -19,9 +19,9 @@ function Map.removeMatches(t, values)
return true return true
end end
for k,v in pairs(t) do for _, key in pairs(Util.keys(t)) do
if matchAll(v) then if matchAll(t[key]) then
t[k] = nil t[key] = nil
end end
end end
end end

View File

@ -106,6 +106,17 @@ local function selectDestination(pts, box, grid)
end end
end end
local function updateCanvas(path)
local t = { }
for node in path:nodes() do
table.insert(t, { x = node.x, y = node.y, z = node.z })
end
os.queueEvent('canvas', {
type = 'canvas_path',
data = t,
})
end
local function pathTo(dest, options) local function pathTo(dest, options)
local blocks = options.blocks or turtle.getState().blocks or { } local blocks = options.blocks or turtle.getState().blocks or { }
local dests = options.dest or { dest } -- support alternative destinations local dests = options.dest or { dest } -- support alternative destinations
@ -156,6 +167,8 @@ local function pathTo(dest, options)
if not path then if not path then
Util.removeByValue(dests, dest) Util.removeByValue(dests, dest)
else else
updateCanvas(path)
path:filter() path:filter()
for node in path:nodes() do for node in path:nodes() do
@ -173,11 +186,19 @@ local function pathTo(dest, options)
-- use single turn method so the turtle doesn't turn around -- use single turn method so the turtle doesn't turn around
-- when encountering obstacles -- when encountering obstacles
if not turtle.gotoSingleTurn(pt.x, pt.y, pt.z, pt.heading) then --if not turtle.gotoSingleTurn(pt.x, pt.y, pt.z, pt.heading) then
--if not turtle.goto(pt) then pt.heading = nil
if not turtle.go(pt) then
local bpt = Point.nearestTo(turtle.point, pt) local bpt = Point.nearestTo(turtle.point, pt)
if turtle.getFuelLevel() == 0 then
return false, 'Out of fuel'
end
table.insert(blocks, bpt) table.insert(blocks, bpt)
os.queueEvent('canvas', {
type = 'canvas_barrier',
data = { bpt },
})
-- really need to check if the block we ran into was a turtle. -- really need to check if the block we ran into was a turtle.
-- if so, this block should be temporary (1-2 secs) -- if so, this block should be temporary (1-2 secs)

View File

@ -131,8 +131,11 @@ end
function Point.calculateMoves(pta, ptb, distance) function Point.calculateMoves(pta, ptb, distance)
local heading = pta.heading local heading = pta.heading
local moves = distance or Point.turtleDistance(pta, ptb) local moves = distance or Point.turtleDistance(pta, ptb)
local weighted = moves
if (pta.heading % 2) == 0 and pta.z ~= ptb.z then if (pta.heading % 2) == 0 and pta.z ~= ptb.z then
moves = moves + 1 moves = moves + 1
weighted = weighted + .9
if ptb.heading and (ptb.heading % 2 == 1) then if ptb.heading and (ptb.heading % 2 == 1) then
heading = ptb.heading heading = ptb.heading
elseif ptb.z > pta.z then elseif ptb.z > pta.z then
@ -142,6 +145,7 @@ function Point.calculateMoves(pta, ptb, distance)
end end
elseif (pta.heading % 2) == 1 and pta.x ~= ptb.x then elseif (pta.heading % 2) == 1 and pta.x ~= ptb.x then
moves = moves + 1 moves = moves + 1
weighted = weighted + .9
if ptb.heading and (ptb.heading % 2 == 0) then if ptb.heading and (ptb.heading % 2 == 0) then
heading = ptb.heading heading = ptb.heading
elseif ptb.x > pta.x then elseif ptb.x > pta.x then
@ -152,15 +156,18 @@ function Point.calculateMoves(pta, ptb, distance)
end end
if not ptb.heading then if not ptb.heading then
return moves, heading, moves return moves, heading, weighted
end end
-- need to know if we are in digging mode
-- if so, we need to face blocks -- need a no-backwards flag
-- calc turns as slightly less than moves -- calc turns as slightly less than moves
local weighted = moves -- local weighted = moves
if heading ~= ptb.heading then if heading ~= ptb.heading then
local turns = Point.calculateTurns(heading, ptb.heading) local turns = Point.calculateTurns(heading, ptb.heading)
moves = moves + turns moves = moves + turns
local wturns = { [0] = 0, [1] = .9, [2] = 1.9 } local wturns = { [0] = 0, [1] = .9, [2] = 1.8 }
weighted = weighted + wturns[turns] weighted = weighted + wturns[turns]
heading = ptb.heading heading = ptb.heading
end end

View File

@ -1,32 +0,0 @@
local Socket = require('socket')
local Proxy = { }
function Proxy.create(remoteId, uri)
local socket, msg = Socket.connect(remoteId, 188)
if not socket then
error(msg)
end
socket.co = coroutine.running()
socket:write(uri)
local methods = socket:read(2) or error('Timed out')
local hijack = { }
for _,method in pairs(methods) do
hijack[method] = function(...)
socket:write({ method, ... })
local resp = socket:read()
if not resp then
error('timed out: ' .. method)
end
return table.unpack(resp)
end
end
return hijack, socket
end
return Proxy

View File

@ -1,95 +0,0 @@
local device = _G.device
local os = _G.os
local rttp = { }
local computerId = os.getComputerID()
local function parse(url, default)
-- initialize default parameters
local parsed = {}
local authority
for i,v in pairs(default or parsed) do parsed[i] = v end
-- remove whitespace
-- url = string.gsub(url, "%s", "")
-- Decode unreserved characters
url = string.gsub(url, "%%(%x%x)", function(hex)
local char = string.char(tonumber(hex, 16))
if string.match(char, "[a-zA-Z0-9._~-]") then
return char
end
-- Hex encodings that are not unreserved must be preserved.
return nil
end)
-- get fragment
url = string.gsub(url, "#(.*)$", function(f)
parsed.fragment = f
return ""
end)
-- get scheme. Lower-case according to RFC 3986 section 3.1.
url = string.gsub(url, "^(%w[%w.+-]*):",
function(s) parsed.scheme = string.lower(s); return "" end)
-- get authority
url = string.gsub(url, "^//([^/]*)", function(n)
authority = n
return ""
end)
-- get query stringing
url = string.gsub(url, "%?(.*)", function(q)
parsed.query = q
return ""
end)
-- get params
url = string.gsub(url, "%;(.*)", function(p)
parsed.params = p
return ""
end)
-- path is whatever was left
parsed.path = url
-- Represents host:port, port = nil if not used.
if authority then
authority = string.gsub(authority, ":(%d+)$",
function(p) parsed.port = tonumber(p); return "" end)
if authority ~= "" then
parsed.host = authority
end
end
return parsed
end
function rttp.get(url)
local modem = device.wireless_modem or error('Modem not found')
local parsed = parse(url, { port = 80 })
parsed.host = tonumber(parsed.host) or error('Invalid url')
for i = 16384, 32767 do
if not modem.isOpen(i) then
modem.open(i)
local path = parsed.query and parsed.path .. '?' .. parsed.query or parsed.path
modem.transmit(parsed.port, parsed.host, {
method = 'GET',
replyAddress = computerId,
replyPort = i,
path = path,
})
local timerId = os.startTimer(3)
repeat
local event, id, dport, dhost, response = os.pullEvent()
if event == 'modem_message' and
dport == i and
dhost == computerId and
type(response) == 'table' then
modem.close(i)
return true, response
end
until event == 'timer' and id == timerId
return false, 'timeout'
end
end
end
return rttp

200
sys/apis/sha2.lua Normal file
View File

@ -0,0 +1,200 @@
-- SHA-256, HMAC and PBKDF2 functions in ComputerCraft
-- By Anavrins
local bit = _G.bit
local mod32 = 2^32
local band = bit32 and bit32.band or bit.band
local bnot = bit32 and bit32.bnot or bit.bnot
local bxor = bit32 and bit32.bxor or bit.bxor
local blshift = bit32 and bit32.lshift or bit.blshift
local upack = unpack
local function rrotate(n, b)
local s = n/(2^b)
local f = s%1
return (s-f) + f*mod32
end
local function brshift(int, by)
local s = int / (2^by)
return s - s%1
end
local H = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
}
local K = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
}
local function counter(incr)
local t1, t2 = 0, 0
if 0xFFFFFFFF - t1 < incr then
t2 = t2 + 1
t1 = incr - (0xFFFFFFFF - t1) - 1
else t1 = t1 + incr
end
return t2, t1
end
local function BE_toInt(bs, i)
return blshift((bs[i] or 0), 24) + blshift((bs[i+1] or 0), 16) + blshift((bs[i+2] or 0), 8) + (bs[i+3] or 0)
end
local function preprocess(data)
local len = #data
local proc = {}
data[#data+1] = 0x80
while #data%64~=56 do data[#data+1] = 0 end
local blocks = math.ceil(#data/64)
for i = 1, blocks do
proc[i] = {}
for j = 1, 16 do
proc[i][j] = BE_toInt(data, 1+((i-1)*64)+((j-1)*4))
end
end
proc[blocks][15], proc[blocks][16] = counter(len*8)
return proc
end
local function digestblock(w, C)
for j = 17, 64 do
--local v = w[j-15]
local s0 = bxor(bxor(rrotate(w[j-15], 7), rrotate(w[j-15], 18)), brshift(w[j-15], 3))
local s1 = bxor(bxor(rrotate(w[j-2], 17), rrotate(w[j-2], 19)), brshift(w[j-2], 10))
w[j] = (w[j-16] + s0 + w[j-7] + s1)%mod32
end
local a, b, c, d, e, f, g, h = upack(C)
for j = 1, 64 do
local S1 = bxor(bxor(rrotate(e, 6), rrotate(e, 11)), rrotate(e, 25))
local ch = bxor(band(e, f), band(bnot(e), g))
local temp1 = (h + S1 + ch + K[j] + w[j])%mod32
local S0 = bxor(bxor(rrotate(a, 2), rrotate(a, 13)), rrotate(a, 22))
local maj = bxor(bxor(band(a, b), band(a, c)), band(b, c))
local temp2 = (S0 + maj)%mod32
h, g, f, e, d, c, b, a = g, f, e, (d+temp1)%mod32, c, b, a, (temp1+temp2)%mod32
end
C[1] = (C[1] + a)%mod32
C[2] = (C[2] + b)%mod32
C[3] = (C[3] + c)%mod32
C[4] = (C[4] + d)%mod32
C[5] = (C[5] + e)%mod32
C[6] = (C[6] + f)%mod32
C[7] = (C[7] + g)%mod32
C[8] = (C[8] + h)%mod32
return C
end
local mt = {
__tostring = function(a) return string.char(unpack(a)) end,
__index = {
toHex = function(self) return ("%02x"):rep(#self):format(unpack(self)) end,
isEqual = function(self, t)
if type(t) ~= "table" then return false end
if #self ~= #t then return false end
local ret = 0
for i = 1, #self do
ret = bit32.bor(ret, bxor(self[i], t[i]))
end
return ret == 0
end
}
}
local function toBytes(t, n)
local b = {}
for i = 1, n do
b[(i-1)*4+1] = band(brshift(t[i], 24), 0xFF)
b[(i-1)*4+2] = band(brshift(t[i], 16), 0xFF)
b[(i-1)*4+3] = band(brshift(t[i], 8), 0xFF)
b[(i-1)*4+4] = band(t[i], 0xFF)
end
return setmetatable(b, mt)
end
local function digest(data)
data = data or ""
data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)}
data = preprocess(data)
local C = {upack(H)}
for i = 1, #data do C = digestblock(data[i], C) end
return toBytes(C, 8)
end
local function hmac(data, key)
data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)}
key = type(key) == "table" and {upack(key)} or {tostring(key):byte(1,-1)}
local blocksize = 64
key = #key > blocksize and digest(key) or key
local ipad = {}
local opad = {}
local padded_key = {}
for i = 1, blocksize do
ipad[i] = bxor(0x36, key[i] or 0)
opad[i] = bxor(0x5C, key[i] or 0)
end
for i = 1, #data do
ipad[blocksize+i] = data[i]
end
ipad = digest(ipad)
for i = 1, blocksize do
padded_key[i] = opad[i]
padded_key[blocksize+i] = ipad[i]
end
return digest(padded_key)
end
local function pbkdf2(pass, salt, iter, dklen)
local hashlen = 32
local block = 1
local out = {}
dklen = dklen or 32
salt = type(salt) == "table" and salt or {tostring(salt):byte(1,-1)}
while dklen > 0 do
local ikey = {}
local isalt = {upack(salt)}
local clen = dklen > hashlen and hashlen or dklen
isalt[#isalt+1] = band(brshift(block, 24), 0xFF)
isalt[#isalt+1] = band(brshift(block, 16), 0xFF)
isalt[#isalt+1] = band(brshift(block, 8), 0xFF)
isalt[#isalt+1] = band(block, 0xFF)
for j = 1, iter do
isalt = hmac(isalt, pass)
for k = 1, clen do ikey[k] = bxor(isalt[k], ikey[k] or 0) end
if j % 200 == 0 then os.queueEvent("PBKDF2", j) coroutine.yield("PBKDF2") end
end
dklen = dklen - clen
block = block+1
for k = 1, clen do out[#out+1] = ikey[k] end
end
return setmetatable(out, mt)
end
return {
digest = digest,
hmac = hmac,
pbkdf2 = pbkdf2,
}

View File

@ -329,14 +329,23 @@ function UI.Grid:drawRows()
local rawRow = self.values[key] local rawRow = self.values[key]
local row = self:getDisplayValues(rawRow, key) local row = self:getDisplayValues(rawRow, key)
local ind = ' '
if self.focused and index == self.index and not self.inactive then
ind = self.focusIndicator
end
local selected = index == self.index and not self.inactive local selected = index == self.index and not self.inactive
local bg = self:getRowBackgroundColor(rawRow, selected) local bg = self:getRowBackgroundColor(rawRow, selected)
local fg = self:getRowTextColor(rawRow, selected) local fg = self:getRowTextColor(rawRow, selected)
local focused = self.focused and selected
self:drawRow(sb, row, focused, bg, fg)
sb:finish(bg)
end
if sb.y <= self.height then
self:clearArea(1, sb.y, self.width, self.height - sb.y + 1)
end
end
function UI.Grid:drawRow(sb, row, focused, bg, fg)
local ind = focused and self.focusIndicator or ' '
for _,col in pairs(self.columns) do for _,col in pairs(self.columns) do
sb:write(ind .. safeValue(row[col.key] or ''), sb:write(ind .. safeValue(row[col.key] or ''),
@ -346,12 +355,6 @@ function UI.Grid:drawRows()
fg) fg)
ind = ' ' ind = ' '
end end
sb:finish(bg)
end
if sb.y <= self.height then
self:clearArea(1, sb.y, self.width, self.height - sb.y + 1)
end
end end
function UI.Grid:getRowTextColor(row, selected) function UI.Grid:getRowTextColor(row, selected)

View File

@ -560,7 +560,7 @@ function Util.insertString(str, istr, pos)
end end
function Util.split(str, pattern) function Util.split(str, pattern)
if not str then error('Util.split: Invalid parameters', 2) end if not str or type(str) ~= 'string' then error('Util.split: Invalid parameters', 2) end
pattern = pattern or "(.-)\n" pattern = pattern or "(.-)\n"
local t = {} local t = {}
local function helper(line) table.insert(t, line) return "" end local function helper(line) table.insert(t, line) return "" end

View File

@ -294,7 +294,6 @@ end
function page:rawExecute(s) function page:rawExecute(s)
local fn, m local fn, m
local wrapped local wrapped
local t = os.clock()
fn = load('return (' ..s.. ')', 'lua', nil, sandboxEnv) fn = load('return (' ..s.. ')', 'lua', nil, sandboxEnv)
@ -303,6 +302,7 @@ function page:rawExecute(s)
wrapped = true wrapped = true
end end
local t = os.clock()
if fn then if fn then
fn, m = pcall(fn) fn, m = pcall(fn)
if #m <= 1 and wrapped then if #m <= 1 and wrapped then
@ -311,19 +311,24 @@ function page:rawExecute(s)
else else
fn, m = load(s, 'lua', nil, sandboxEnv) fn, m = load(s, 'lua', nil, sandboxEnv)
if fn then if fn then
t = os.clock()
fn, m = pcall(fn) fn, m = pcall(fn)
end end
end end
if fn then if fn then
if m or wrapped then t = os.clock() - t
local bg, fg = term.getBackgroundColor(), term.getTextColor() local bg, fg = term.getBackgroundColor(), term.getTextColor()
term.setTextColor(colors.cyan) term.setTextColor(colors.cyan)
term.setBackgroundColor(colors.black) term.setBackgroundColor(colors.black)
term.write(string.format('out [%.2f]: ', os.clock() - t)) term.write(string.format('out [%.2f]: ', t))
term.setBackgroundColor(bg) term.setBackgroundColor(bg)
term.setTextColor(fg) term.setTextColor(fg)
if m or wrapped then
Util.print(m or 'nil') Util.print(m or 'nil')
else
print()
end end
else else
_G.printError(m) _G.printError(m)

View File

@ -127,12 +127,14 @@ local function sendCommand(host, command)
end end
end end
--[[
function page.ports:eventHandler(event) function page.ports:eventHandler(event)
if event.type == 'grid_select' then if event.type == 'grid_select' then
shell.openForegroundTab('sniff ' .. event.selected.port) shell.openForegroundTab('sniff ' .. event.selected.port)
end end
return UI.SlideOut.eventHandler(self, event) return UI.SlideOut.eventHandler(self, event)
end end
]]
function page.ports.grid:update() function page.ports.grid:update()
local function findConnection(port) local function findConnection(port)

View File

@ -24,4 +24,4 @@ kernel.hook('kernel_focus', function(_, eventData)
end end
end) end)
while os.pullEventRaw() do end os.pullEventRaw('kernel_halt')

View File

@ -1,115 +0,0 @@
local Event = require('event')
local Util = require('util')
local fs = _G.fs
local modem = _G.device.wireless_modem
local os = _G.os
local computerId = os.getComputerID()
--modem.open(80)
-- https://github.com/golgote/neturl/blob/master/lib/net/url.lua
local function parseQuery(str)
local sep = '&'
local values = {}
for key,val in str:gmatch(string.format('([^%q=]+)(=*[^%q=]*)', sep, sep)) do
--local key = decode(key)
local keys = {}
key = key:gsub('%[([^%]]*)%]', function(v)
-- extract keys between balanced brackets
if string.find(v, "^-?%d+$") then
v = tonumber(v)
--else
--v = decode(v)
end
table.insert(keys, v)
return "="
end)
key = key:gsub('=+.*$', "")
key = key:gsub('%s', "_") -- remove spaces in parameter name
val = val:gsub('^=+', "")
if not values[key] then
values[key] = {}
end
if #keys > 0 and type(values[key]) ~= 'table' then
values[key] = {}
elseif #keys == 0 and type(values[key]) == 'table' then
values[key] = val --decode(val)
end
local t = values[key]
for i,k in ipairs(keys) do
if type(t) ~= 'table' then
t = {}
end
if k == "" then
k = #t+1
end
if not t[k] then
t[k] = {}
end
if i == #keys then
t[k] = val --decode(val)
end
t = t[k]
end
end
return values
end
local function getListing(path, recursive)
local list = { }
local function listing(p)
for _, f in pairs(fs.listEx(p)) do
local abs = fs.combine(p, f.name)
table.insert(list, {
isDir = f.isDir,
path = string.sub(abs, #path + 1),
size = f.size,
})
if recursive and f.isDir then
listing(abs)
end
end
end
listing(path)
return list
end
--[[
Event.on('modem_message', function(_, _, dport, dhost, request)
if dport == 80 and dhost == computerId and type(request) == 'table' then
if request.method == 'GET' then
local query
if not request.path or type(request.path) ~= 'string' then
return
end
local path = request.path:gsub('%?(.*)', function(v)
query = parseQuery(v)
return ''
end)
if fs.isDir(path) then
-- TODO: more validation
modem.transmit(request.replyPort, request.replyAddress, {
statusCode = 200,
contentType = 'table/directory',
data = getListing(path, query and query.recursive == 'true'),
})
elseif fs.exists(path) then
modem.transmit(request.replyPort, request.replyAddress, {
statusCode = 200,
contentType = 'table/file',
data = Util.readFile(path),
})
else
modem.transmit(request.replyPort, request.replyAddress, {
statusCode = 404,
})
end
end
end
end)
]]

View File

@ -156,7 +156,7 @@ local function sendInfo()
info.label = os.getComputerLabel() info.label = os.getComputerLabel()
info.uptime = math.floor(os.clock()) info.uptime = math.floor(os.clock())
info.group = network.getGroup() info.group = network.getGroup()
if turtle then if turtle and turtle.getStatus then
info.fuel = turtle.getFuelLevel() info.fuel = turtle.getFuelLevel()
info.status = turtle.getStatus() info.status = turtle.getStatus()
info.point = turtle.point info.point = turtle.point

View File

@ -1,69 +0,0 @@
local Event = require('event')
local Terminal = require('terminal')
local Util = require('util')
local colors = _G.colors
local modem = _G.device.wireless_modem
local term = _G.term
local textutils = _G.textutils
local terminal = Terminal.window(term.current())
terminal.setMaxScroll(300)
local oldTerm = term.redirect(terminal)
local function syntax()
error('Syntax: sniff [port]')
end
local port = ({ ... })[1] or syntax()
port = tonumber(port) or syntax()
Event.on('modem_message',
function(_, _, dport, _, data, _)
if dport == port then
terminal.scrollBottom()
terminal.setTextColor(colors.white)
print(textutils.serialize(data))
end
end)
Event.on('mouse_scroll', function(_, direction)
if direction == -1 then
terminal.scrollUp()
else
terminal.scrollDown()
end
end)
local function sniffer(_, _, data)
terminal.scrollBottom()
terminal.setTextColor(colors.yellow)
local ot = term.redirect(terminal)
print(textutils.serialize(data))
term.redirect(ot)
end
local socket = _G.transport.sockets[port]
if socket then
if not socket.sniffers then
socket.sniffers = { modem.transmit }
socket.transmit = function(...)
for _,v in pairs(socket.sniffers) do
v(...)
end
end
end
table.insert(socket.sniffers, sniffer)
end
local s, m = pcall(Event.pullEvents)
if socket then
Util.removeByValue(socket.sniffers, sniffer)
end
term.redirect(oldTerm)
if not s and m then
error(m)
end

View File

@ -6,7 +6,9 @@ local help = _G.help
local shell = _ENV.shell local shell = _ENV.shell
if not fs.exists('usr/config/packages') then if not fs.exists('usr/config/packages') then
pcall(function()
Packages:downloadList() Packages:downloadList()
end)
end end
local appPaths = Util.split(shell.path(), '(.-):') local appPaths = Util.split(shell.path(), '(.-):')

View File

@ -52,6 +52,7 @@ function turtle.resetState()
state.movePolicy = _defaultMove state.movePolicy = _defaultMove
state.moveCallback = noop state.moveCallback = noop
state.blacklist = nil state.blacklist = nil
state.reference = nil -- gps reference when converting to relative coords
Pathing.reset() Pathing.reset()
return true return true
end end
@ -77,8 +78,6 @@ local function _dig(name, inspect, dig)
return dig() return dig()
end end
-- override dig
-- optionally check that the block is a certain type
function turtle.dig(s) function turtle.dig(s)
return _dig(s, turtle.inspect, turtle.native.dig) return _dig(s, turtle.inspect, turtle.native.dig)
end end
@ -359,7 +358,7 @@ function turtle.set(args)
turtle.setDigPolicy(turtle.getPolicy(v)) turtle.setDigPolicy(turtle.getPolicy(v))
elseif k == 'movePolicy' then elseif k == 'movePolicy' then
turtle.setMovePolicy(turtle.getPolicy(v)) state.movePolicy = turtle.getPolicy(v)
elseif k == 'movementStrategy' then elseif k == 'movementStrategy' then
turtle.setMovementStrategy(v) turtle.setMovementStrategy(v)
@ -379,6 +378,9 @@ function turtle.set(args)
elseif k == 'blacklist' then elseif k == 'blacklist' then
state.blacklist = v state.blacklist = v
elseif k == 'reference' then
state.reference = v
else else
error('Invalid turle.set: ' .. tostring(k)) error('Invalid turle.set: ' .. tostring(k))
end end
@ -426,6 +428,10 @@ function turtle.setHeading(heading)
return false, 'Invalid heading' return false, 'Invalid heading'
end end
if heading == turtle.point.heading then
return turtle.point
end
local fi = Point.facings[heading] local fi = Point.facings[heading]
if not fi then if not fi then
return false, 'Invalid heading' return false, 'Invalid heading'