mirror of
https://github.com/kepler155c/opus
synced 2025-01-16 18:32:52 +00:00
spaces->tabs + cleanup + pathing fixes
This commit is contained in:
parent
82ec4db50f
commit
3c22a872b0
@ -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
|
|
@ -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
|
||||||
|
@ -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
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------ encoding
|
local function quotestring (value)
|
||||||
|
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
|
||||||
|
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
|
||||||
|
if strfind (value, "[\194\216\220\225\226\239]") then
|
||||||
|
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
|
||||||
|
return "\"" .. value .. "\""
|
||||||
|
end
|
||||||
|
json.quotestring = quotestring
|
||||||
|
|
||||||
local function encodeCommon(val, pretty, tabLevel, tTracking)
|
local function replace(str, o, n)
|
||||||
local str = ""
|
local i, j = strfind (str, o, 1, true)
|
||||||
|
if i then
|
||||||
-- Tabbing util
|
return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
|
||||||
local function tab(s)
|
|
||||||
str = str .. ("\t"):rep(tabLevel) .. s
|
|
||||||
end
|
|
||||||
|
|
||||||
local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc)
|
|
||||||
str = str .. bracket
|
|
||||||
if pretty then
|
|
||||||
str = str .. "\n"
|
|
||||||
tabLevel = tabLevel + 1
|
|
||||||
end
|
|
||||||
for k,v in iterator(val) do
|
|
||||||
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
|
|
||||||
|
|
||||||
-- Table encoding
|
|
||||||
if type(val) == "table" then
|
|
||||||
assert(not tTracking[val], "Cannot encode a table holding itself recursively")
|
|
||||||
tTracking[val] = true
|
|
||||||
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
|
end
|
||||||
|
|
||||||
function json.encode(val)
|
-- locale independent num2str and str2num functions
|
||||||
return encodeCommon(val, false, 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.encodePretty(val)
|
updatedecpoint()
|
||||||
return encodeCommon(val, true, 0, {})
|
|
||||||
|
local function num2str (num)
|
||||||
|
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
|
||||||
end
|
end
|
||||||
|
|
||||||
function json.encodeToFile(path, val)
|
local function str2num (str)
|
||||||
local file = io.open(path, "w")
|
local num = tonumber(replace(str, ".", decpoint))
|
||||||
assert(file, "Unable to open file")
|
if not num then
|
||||||
file:write(json.encodePretty(val))
|
updatedecpoint()
|
||||||
file:close()
|
num = tonumber(replace(str, ".", decpoint))
|
||||||
|
end
|
||||||
|
return num
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------ decoding
|
local function addnewline2 (level, buffer, buflen)
|
||||||
|
buffer[buflen+1] = "\n"
|
||||||
local decodeControls = {}
|
buffer[buflen+2] = strrep (" ", level)
|
||||||
for k,v in pairs(controls) do
|
buflen = buflen + 2
|
||||||
decodeControls[v] = k
|
return buflen
|
||||||
end
|
end
|
||||||
|
|
||||||
local function parseBoolean(str)
|
function json.addnewline (state)
|
||||||
if str:sub(1, 4) == "true" then
|
if state.indent then
|
||||||
return true, removeWhite(str:sub(5))
|
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
|
||||||
end
|
line = line + 1
|
||||||
|
linepos = pos
|
||||||
function json.parseObject(str)
|
pos = pos + 1
|
||||||
str = removeWhite(str:sub(2))
|
else
|
||||||
|
break
|
||||||
local val = {}
|
|
||||||
while str:sub(1, 1) ~= "}" do
|
|
||||||
local k, v
|
|
||||||
k, v, str = json.parseMember(str)
|
|
||||||
val[k] = v
|
|
||||||
str = removeWhite(str)
|
|
||||||
end
|
end
|
||||||
str = removeWhite(str:sub(2))
|
end
|
||||||
return val, str
|
return "line " .. line .. ", column " .. (where - linepos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function json.decode(str)
|
local function unterminated (str, what, where)
|
||||||
str = removeWhite(str)
|
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
|
||||||
return json.parseValue(str)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function scanwhite (str, pos)
|
||||||
|
while true do
|
||||||
|
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
|
||||||
|
|
||||||
|
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())
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
@ -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
200
sys/apis/sha2.lua
Normal 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,
|
||||||
|
}
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -24,4 +24,4 @@ kernel.hook('kernel_focus', function(_, eventData)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
while os.pullEventRaw() do end
|
os.pullEventRaw('kernel_halt')
|
@ -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)
|
|
||||||
]]
|
|
@ -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
|
||||||
|
@ -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
|
|
@ -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(), '(.-):')
|
||||||
|
@ -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'
|
||||||
|
Loading…
Reference in New Issue
Block a user