mirror of
https://github.com/kepler155c/opus
synced 2025-01-23 21:56:53 +00:00
reorganization
This commit is contained in:
parent
64c68f2662
commit
36fd5ca073
@ -2,12 +2,12 @@ local git = require('git')
|
||||
|
||||
local gitfs = { }
|
||||
|
||||
function gitfs.mount(dir, user, repo, branch)
|
||||
if not user or not repo then
|
||||
error('gitfs syntax: user, repo, [branch]')
|
||||
function gitfs.mount(dir, repo)
|
||||
if not repo then
|
||||
error('gitfs syntax: repo')
|
||||
end
|
||||
|
||||
local list = git.list(user, repo, branch)
|
||||
local list = git.list(repo)
|
||||
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)
|
||||
|
@ -6,8 +6,13 @@ local FILE_URL = 'https://raw.github.com/%s/%s/%s/%s'
|
||||
|
||||
local git = { }
|
||||
|
||||
function git.list(user, repo, branch)
|
||||
branch = branch or 'master'
|
||||
function git.list(repo)
|
||||
|
||||
local t = Util.split(repo, '(.-)/')
|
||||
|
||||
local user = t[1]
|
||||
local repo = t[2]
|
||||
local branch = t[3] or 'master'
|
||||
|
||||
local dataUrl = string.format(TREE_URL, user, repo, branch)
|
||||
local contents = Util.download(dataUrl)
|
||||
|
@ -379,8 +379,15 @@ function Util.download(url, filename)
|
||||
end
|
||||
|
||||
function Util.loadUrl(url, env) -- loadfile equivalent
|
||||
local c = Util.download(url)
|
||||
return load(c, url, nil, env)
|
||||
local s, m = pcall(function()
|
||||
local c = Util.download(url)
|
||||
return load(c, url, nil, env)
|
||||
end)
|
||||
|
||||
if s then
|
||||
return m
|
||||
end
|
||||
return s, m
|
||||
end
|
||||
|
||||
function Util.runUrl(env, url, ...) -- os.run equivalent
|
||||
@ -390,7 +397,7 @@ function Util.runUrl(env, url, ...) -- os.run equivalent
|
||||
fn, m = pcall(function() fn(unpack(args)) end)
|
||||
end
|
||||
if not fn and m and m ~= '' then
|
||||
printError(m)
|
||||
-- printError(m)
|
||||
end
|
||||
return fn, m
|
||||
end
|
||||
|
@ -1,414 +0,0 @@
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Config = require('config')
|
||||
local SHA1 = require('sha1')
|
||||
local UI = require('ui')
|
||||
local Util = require('util')
|
||||
|
||||
-- scrap this entire file. don't muck with standard apis
|
||||
|
||||
local REGISTRY_DIR = 'usr/.registry'
|
||||
|
||||
|
||||
-- FIX SOMEDAY
|
||||
function os.registerApp(app, key)
|
||||
|
||||
app.key = SHA1.sha1(key)
|
||||
Util.writeTable(fs.combine(REGISTRY_DIR, app.key), app)
|
||||
os.queueEvent('os_register_app')
|
||||
end
|
||||
|
||||
function os.unregisterApp(key)
|
||||
|
||||
local filename = fs.combine(REGISTRY_DIR, SHA1.sha1(key))
|
||||
if fs.exists(filename) then
|
||||
fs.delete(filename)
|
||||
os.queueEvent('os_register_app')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local sandboxEnv = Util.shallowCopy(getfenv(1))
|
||||
setmetatable(sandboxEnv, { __index = _G })
|
||||
|
||||
multishell.setTitle(multishell.getCurrent(), 'App Store')
|
||||
UI:configure('Appstore', ...)
|
||||
|
||||
local APP_DIR = 'usr/apps'
|
||||
|
||||
local sources = {
|
||||
|
||||
{ text = "STD Default",
|
||||
event = 'source',
|
||||
url = "http://pastebin.com/raw/zVws7eLq" }, --stock
|
||||
--[[
|
||||
{ text = "Discover",
|
||||
event = 'source',
|
||||
generateName = true,
|
||||
url = "http://pastebin.com/raw/9bXfCz6M" }, --owned by dannysmc95
|
||||
|
||||
{ text = "Opus",
|
||||
event = 'source',
|
||||
url = "http://pastebin.com/raw/ajQ91Rmn" },
|
||||
]]
|
||||
}
|
||||
|
||||
shell.setDir(APP_DIR)
|
||||
|
||||
function downloadApp(app)
|
||||
local h
|
||||
|
||||
if type(app.url) == "table" then
|
||||
h = contextualGet(app.url[1])
|
||||
else
|
||||
h = http.get(app.url)
|
||||
end
|
||||
|
||||
if h then
|
||||
local contents = h.readAll()
|
||||
h:close()
|
||||
return contents
|
||||
end
|
||||
end
|
||||
|
||||
function runApp(app, checkExists, ...)
|
||||
|
||||
local path, fn
|
||||
local args = { ... }
|
||||
|
||||
if checkExists and fs.exists(fs.combine(APP_DIR, app.name)) then
|
||||
path = fs.combine(APP_DIR, app.name)
|
||||
else
|
||||
local program = downloadApp(app)
|
||||
|
||||
fn = function()
|
||||
|
||||
if not program then
|
||||
error('Failed to download')
|
||||
end
|
||||
|
||||
local fn = loadstring(program, app.name)
|
||||
|
||||
if not fn then
|
||||
error('Failed to download')
|
||||
end
|
||||
|
||||
setfenv(fn, sandboxEnv)
|
||||
fn(unpack(args))
|
||||
end
|
||||
end
|
||||
|
||||
multishell.openTab({
|
||||
title = app.name,
|
||||
env = sandboxEnv,
|
||||
path = path,
|
||||
fn = fn,
|
||||
focused = true,
|
||||
})
|
||||
|
||||
return true, 'Running program'
|
||||
end
|
||||
|
||||
local installApp = function(app)
|
||||
|
||||
local program = downloadApp(app)
|
||||
if not program then
|
||||
return false, "Failed to download"
|
||||
end
|
||||
|
||||
local fullPath = fs.combine(APP_DIR, app.name)
|
||||
Util.writeFile(fullPath, program)
|
||||
return true, 'Installed as ' .. fullPath
|
||||
end
|
||||
|
||||
local viewApp = function(app)
|
||||
|
||||
local program = downloadApp(app)
|
||||
if not program then
|
||||
return false, "Failed to download"
|
||||
end
|
||||
|
||||
Util.writeFile('/.source', program)
|
||||
shell.openForegroundTab('edit /.source')
|
||||
fs.delete('/.source')
|
||||
return true
|
||||
end
|
||||
|
||||
local getSourceListing = function(source)
|
||||
local contents = http.get(source.url)
|
||||
if contents then
|
||||
|
||||
local fn = loadstring(contents.readAll(), source.text)
|
||||
contents.close()
|
||||
|
||||
local env = { std = { } }
|
||||
setmetatable(env, { __index = _G })
|
||||
setfenv(fn, env)
|
||||
fn()
|
||||
|
||||
if env.contextualGet then
|
||||
contextualGet = env.contextualGet
|
||||
end
|
||||
|
||||
source.storeURLs = env.std.storeURLs
|
||||
source.storeCatagoryNames = env.std.storeCatagoryNames
|
||||
|
||||
if source.storeURLs and source.storeCatagoryNames then
|
||||
for k,v in pairs(source.storeURLs) do
|
||||
if source.generateName then
|
||||
v.name = v.title:match('(%w+)')
|
||||
if not v.name or #v.name == 0 then
|
||||
v.name = tostring(k)
|
||||
else
|
||||
v.name = v.name:lower()
|
||||
end
|
||||
else
|
||||
v.name = k
|
||||
end
|
||||
v.categoryName = source.storeCatagoryNames[v.catagory]
|
||||
v.ltitle = v.title:lower()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local appPage = UI.Page({
|
||||
backgroundColor = UI.ViewportWindow.defaults.backgroundColor,
|
||||
menuBar = UI.MenuBar({
|
||||
showBackButton = not pocket,
|
||||
buttons = {
|
||||
{ text = 'Install', event = 'install' },
|
||||
{ text = 'Run', event = 'run' },
|
||||
{ text = 'View', event = 'view' },
|
||||
{ text = 'Remove', event = 'uninstall', name = 'removeButton' },
|
||||
},
|
||||
}),
|
||||
container = UI.Window({
|
||||
x = 2,
|
||||
y = 3,
|
||||
height = UI.term.height - 3,
|
||||
width = UI.term.width - 2,
|
||||
viewport = UI.ViewportWindow(),
|
||||
}),
|
||||
notification = UI.Notification(),
|
||||
accelerators = {
|
||||
q = 'back',
|
||||
backspace = 'back',
|
||||
},
|
||||
})
|
||||
|
||||
function appPage.container.viewport:draw()
|
||||
local app = self.parent.parent.app
|
||||
local str = string.format(
|
||||
'By: %s\nCategory: %s\nFile name: %s\n\n%s',
|
||||
app.creator, app.categoryName, app.name, app.description)
|
||||
|
||||
self:clear()
|
||||
local y = self:wrappedWrite(1, 1, app.title, self.width, nil, colors.yellow)
|
||||
self.height = self:wrappedWrite(1, y, str, self.width)
|
||||
|
||||
if appPage.notification.enabled then
|
||||
appPage.notification:draw()
|
||||
end
|
||||
end
|
||||
|
||||
function appPage:enable(source, app)
|
||||
self.source = source
|
||||
self.app = app
|
||||
UI.Page.enable(self)
|
||||
|
||||
self.container.viewport:setScrollPosition(0)
|
||||
if fs.exists(fs.combine(APP_DIR, app.name)) then
|
||||
self.menuBar.removeButton:enable('Remove')
|
||||
else
|
||||
self.menuBar.removeButton:disable('Remove')
|
||||
end
|
||||
end
|
||||
|
||||
function appPage:eventHandler(event)
|
||||
if event.type == 'back' then
|
||||
UI:setPreviousPage()
|
||||
|
||||
elseif event.type == 'run' then
|
||||
self.notification:info('Running program', 3)
|
||||
self:sync()
|
||||
runApp(self.app, true)
|
||||
|
||||
elseif event.type == 'view' then
|
||||
self.notification:info('Downloading program', 3)
|
||||
self:sync()
|
||||
viewApp(self.app)
|
||||
|
||||
elseif event.type == 'uninstall' then
|
||||
if self.app.runOnly then
|
||||
s,m = runApp(self.app, false, 'uninstall')
|
||||
else
|
||||
fs.delete(fs.combine(APP_DIR, self.app.name))
|
||||
self.notification:success("Uninstalled " .. self.app.name, 3)
|
||||
self:focusFirst(self)
|
||||
self.menuBar.removeButton:disable('Remove')
|
||||
self.menuBar:draw()
|
||||
|
||||
os.unregisterApp(self.app.creator .. '.' .. self.app.name)
|
||||
end
|
||||
|
||||
elseif event.type == 'install' then
|
||||
self.notification:info("Installing", 3)
|
||||
self:sync()
|
||||
local s, m
|
||||
if self.app.runOnly then
|
||||
s,m = runApp(self.app, false)
|
||||
else
|
||||
s,m = installApp(self.app)
|
||||
end
|
||||
if s then
|
||||
self.notification:success(m, 3)
|
||||
|
||||
if not self.app.runOnly then
|
||||
self.menuBar.removeButton:enable('Remove')
|
||||
self.menuBar:draw()
|
||||
|
||||
local category = 'Apps'
|
||||
if self.app.catagoryName == 'Game' then
|
||||
category = 'Games'
|
||||
end
|
||||
|
||||
os.registerApp({
|
||||
run = fs.combine(APP_DIR, self.app.name),
|
||||
title = self.app.title,
|
||||
category = category,
|
||||
icon = self.app.icon,
|
||||
}, self.app.creator .. '.' .. self.app.name)
|
||||
end
|
||||
else
|
||||
self.notification:error(m, 3)
|
||||
end
|
||||
else
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local categoryPage = UI.Page({
|
||||
menuBar = UI.MenuBar({
|
||||
buttons = {
|
||||
{ text = 'Catalog', event = 'dropdown', dropdown = 'sourceMenu' },
|
||||
{ text = 'Category', event = 'dropdown', dropdown = 'categoryMenu' },
|
||||
},
|
||||
}),
|
||||
sourceMenu = UI.DropMenu({
|
||||
buttons = sources,
|
||||
}),
|
||||
grid = UI.ScrollingGrid({
|
||||
y = 2,
|
||||
height = UI.term.height - 2,
|
||||
columns = {
|
||||
{ heading = 'Title', key = 'title' },
|
||||
},
|
||||
sortColumn = 'title',
|
||||
autospace = true,
|
||||
}),
|
||||
statusBar = UI.StatusBar(),
|
||||
accelerators = {
|
||||
l = 'lua',
|
||||
q = 'quit',
|
||||
},
|
||||
})
|
||||
|
||||
function categoryPage:setCategory(source, name, index)
|
||||
self.grid.values = { }
|
||||
for k,v in pairs(source.storeURLs) do
|
||||
if index == 0 or index == v.catagory then
|
||||
table.insert(self.grid.values, v)
|
||||
end
|
||||
end
|
||||
self.statusBar:setStatus(string.format('%s: %s', source.text, name))
|
||||
self.grid:update()
|
||||
self.grid:setIndex(1)
|
||||
end
|
||||
|
||||
function categoryPage:setSource(source)
|
||||
|
||||
if not source.categoryMenu then
|
||||
|
||||
self.statusBar:setStatus('Loading...')
|
||||
self.statusBar:draw()
|
||||
self:sync()
|
||||
|
||||
getSourceListing(source)
|
||||
|
||||
if not source.storeURLs then
|
||||
error('Unable to download application list')
|
||||
end
|
||||
|
||||
local buttons = { }
|
||||
for k,v in Util.spairs(source.storeCatagoryNames,
|
||||
function(a, b) return a:lower() < b:lower() end) do
|
||||
|
||||
if v ~= 'Operating System' then
|
||||
table.insert(buttons, {
|
||||
text = v,
|
||||
event = 'category',
|
||||
index = k,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
source.categoryMenu = UI.DropMenu({
|
||||
y = 2,
|
||||
x = 1,
|
||||
buttons = buttons,
|
||||
})
|
||||
source.index, source.name = Util.first(source.storeCatagoryNames)
|
||||
|
||||
categoryPage:add({
|
||||
categoryMenu = source.categoryMenu
|
||||
})
|
||||
end
|
||||
|
||||
self.source = source
|
||||
self.categoryMenu = source.categoryMenu
|
||||
categoryPage:setCategory(source, source.name, source.index)
|
||||
end
|
||||
|
||||
function categoryPage.grid:sortCompare(a, b)
|
||||
return a.ltitle < b.ltitle
|
||||
end
|
||||
|
||||
function categoryPage.grid:getRowTextColor(row, selected)
|
||||
if fs.exists(fs.combine(APP_DIR, row.name)) then
|
||||
return colors.orange
|
||||
end
|
||||
return UI.Grid:getRowTextColor(row, selected)
|
||||
end
|
||||
|
||||
function categoryPage:eventHandler(event)
|
||||
|
||||
if event.type == 'grid_select' or event.type == 'select' then
|
||||
UI:setPage(appPage, self.source, self.grid:getSelected())
|
||||
|
||||
elseif event.type == 'category' then
|
||||
self:setCategory(self.source, event.button.text, event.button.index)
|
||||
self:setFocus(self.grid)
|
||||
self:draw()
|
||||
|
||||
elseif event.type == 'source' then
|
||||
self:setFocus(self.grid)
|
||||
self:setSource(event.button)
|
||||
self:draw()
|
||||
|
||||
elseif event.type == 'quit' then
|
||||
UI:exitPullEvents()
|
||||
|
||||
else
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
print("Retrieving catalog list")
|
||||
categoryPage:setSource(sources[1])
|
||||
|
||||
UI:setPage(categoryPage)
|
||||
UI:pullEvents()
|
||||
UI.term:reset()
|
@ -1,132 +0,0 @@
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Event = require('event')
|
||||
local UI = require('ui')
|
||||
local Util = require('util')
|
||||
|
||||
multishell.setTitle(multishell.getCurrent(), 'Events')
|
||||
UI:configure('Events', ...)
|
||||
|
||||
local page = UI.Page({
|
||||
menuBar = UI.MenuBar({
|
||||
buttons = {
|
||||
{ text = 'Filter', event = 'filter' },
|
||||
{ text = 'Reset', event = 'reset' },
|
||||
{ text = 'Pause ', event = 'toggle', name = 'pauseButton' },
|
||||
},
|
||||
}),
|
||||
grid = UI.Grid({
|
||||
y = 2,
|
||||
columns = {
|
||||
{ heading = 'Event', key = 'event' },
|
||||
{ key = 'p1' },
|
||||
{ key = 'p2' },
|
||||
{ key = 'p3' },
|
||||
{ key = 'p4' },
|
||||
{ key = 'p5' },
|
||||
},
|
||||
autospace = true,
|
||||
}),
|
||||
accelerators = {
|
||||
f = 'filter',
|
||||
p = 'toggle',
|
||||
r = 'reset',
|
||||
c = 'clear',
|
||||
q = 'quit',
|
||||
},
|
||||
filtered = { },
|
||||
})
|
||||
|
||||
function page:eventHandler(event)
|
||||
|
||||
if event.type == 'filter' then
|
||||
local entry = self.grid:getSelected()
|
||||
self.filtered[entry.event] = true
|
||||
|
||||
elseif event.type == 'toggle' then
|
||||
self.paused = not self.paused
|
||||
if self.paused then
|
||||
self.menuBar.pauseButton.text = 'Resume'
|
||||
else
|
||||
self.menuBar.pauseButton.text = 'Pause '
|
||||
end
|
||||
self.menuBar:draw()
|
||||
|
||||
elseif event.type == 'grid_select' then
|
||||
multishell.openTab({ path = 'sys/apps/Lua.lua', args = { event.selected }, focused = true })
|
||||
|
||||
elseif event.type == 'reset' then
|
||||
self.filtered = { }
|
||||
self.grid:setValues({ })
|
||||
self.grid:draw()
|
||||
if self.paused then
|
||||
self:emit({ type = 'toggle' })
|
||||
end
|
||||
|
||||
elseif event.type == 'clear' then
|
||||
self.grid:setValues({ })
|
||||
self.grid:draw()
|
||||
|
||||
elseif event.type == 'quit' then
|
||||
Event.exitPullEvents()
|
||||
|
||||
elseif event.type == 'focus_change' then
|
||||
if event.focused == self.grid then
|
||||
if not self.paused then
|
||||
self:emit({ type = 'toggle' })
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function page.grid:getDisplayValues(row)
|
||||
row = Util.shallowCopy(row)
|
||||
|
||||
local function tovalue(s)
|
||||
if type(s) == 'table' then
|
||||
return 'table'
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
for k,v in pairs(row) do
|
||||
row[k] = tovalue(v)
|
||||
end
|
||||
|
||||
return row
|
||||
end
|
||||
|
||||
function page.grid:draw()
|
||||
self:adjustWidth()
|
||||
UI.Grid.draw(self)
|
||||
end
|
||||
|
||||
Event.addRoutine(function()
|
||||
|
||||
while true do
|
||||
local e = { os.pullEvent() }
|
||||
if not page.paused and not page.filtered[e[1]] then
|
||||
table.insert(page.grid.values, 1, {
|
||||
event = e[1],
|
||||
p1 = e[2],
|
||||
p2 = e[3],
|
||||
p3 = e[4],
|
||||
p4 = e[5],
|
||||
p5 = e[6],
|
||||
})
|
||||
if #page.grid.values > page.grid.height - 1 then
|
||||
table.remove(page.grid.values, #page.grid.values)
|
||||
end
|
||||
page.grid:update()
|
||||
page.grid:draw()
|
||||
page:sync()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
UI:setPage(page)
|
||||
UI:pullEvents()
|
@ -288,7 +288,7 @@ function Browser:eventHandler(event)
|
||||
Event.exitPullEvents()
|
||||
|
||||
elseif event.type == 'edit' and file then
|
||||
self:run('sys/apps/shell', '/sys/apps/edit.lua', file.name)
|
||||
self:run('sys/apps/shell', 'edit', file.name)
|
||||
|
||||
elseif event.type == 'shell' then
|
||||
self:run('sys/apps/shell')
|
||||
|
@ -36,6 +36,15 @@ Config.load('Overview', config)
|
||||
local applications = { }
|
||||
|
||||
local function loadApplications()
|
||||
|
||||
local requirements = {
|
||||
turtle = function() return turtle end,
|
||||
advancedTurtle = function() return turtle and term.isColor() end,
|
||||
pocket = function() return pocket end,
|
||||
advancedPocket = function() return pocket and term.isColor() end,
|
||||
advancedComputer = function() return not turtle and not pocket and term.isColor() end,
|
||||
}
|
||||
|
||||
applications = Util.readTable('sys/etc/app.db')
|
||||
|
||||
if fs.exists(REGISTRY_DIR) then
|
||||
@ -50,12 +59,20 @@ local function loadApplications()
|
||||
end
|
||||
|
||||
Util.each(applications, function(v, k) v.key = k end)
|
||||
applications = Util.filter(applications, function(_, a) return not a.disabled end)
|
||||
applications = Util.filter(applications, function(_, a)
|
||||
if a.disabled then
|
||||
return false
|
||||
end
|
||||
|
||||
applications = Util.filter(applications, function(_, a)
|
||||
return Util.startsWidth(a.run, 'http') or shell.resolveProgram(a.run)
|
||||
if a.requires then
|
||||
local fn = requirements[a.requires]
|
||||
if fn and not fn() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return Util.startsWidth(a.run, 'http') or shell.resolveProgram(a.run)
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
loadApplications()
|
||||
|
@ -1,218 +0,0 @@
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Event = require('event')
|
||||
local UI = require('ui')
|
||||
local Util = require('util')
|
||||
|
||||
multishell.setTitle(multishell.getCurrent(), 'Devices')
|
||||
|
||||
--[[ -- PeripheralsPage -- ]] --
|
||||
local peripheralsPage = UI.Page {
|
||||
grid = UI.ScrollingGrid {
|
||||
columns = {
|
||||
{ heading = 'Type', key = 'type' },
|
||||
{ heading = 'Side', key = 'side' },
|
||||
},
|
||||
sortColumn = 'type',
|
||||
height = UI.term.height - 1,
|
||||
autospace = true,
|
||||
},
|
||||
statusBar = UI.StatusBar {
|
||||
status = 'Select peripheral'
|
||||
},
|
||||
accelerators = {
|
||||
q = 'quit',
|
||||
},
|
||||
}
|
||||
|
||||
function peripheralsPage.grid:draw()
|
||||
local sides = peripheral.getNames()
|
||||
|
||||
Util.clear(self.values)
|
||||
for _,side in pairs(sides) do
|
||||
table.insert(self.values, {
|
||||
type = peripheral.getType(side),
|
||||
side = side
|
||||
})
|
||||
end
|
||||
self:update()
|
||||
self:adjustWidth()
|
||||
UI.Grid.draw(self)
|
||||
end
|
||||
|
||||
function peripheralsPage:updatePeripherals()
|
||||
if UI:getCurrentPage() == self then
|
||||
self.grid:draw()
|
||||
self:sync()
|
||||
end
|
||||
end
|
||||
|
||||
function peripheralsPage:eventHandler(event)
|
||||
if event.type == 'quit' then
|
||||
Event.exitPullEvents()
|
||||
|
||||
elseif event.type == 'grid_select' then
|
||||
UI:setPage('methods', event.selected)
|
||||
|
||||
end
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
|
||||
--[[ -- MethodsPage -- ]] --
|
||||
local methodsPage = UI.Page {
|
||||
grid = UI.ScrollingGrid {
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'name', width = UI.term.width }
|
||||
},
|
||||
sortColumn = 'name',
|
||||
height = 7,
|
||||
},
|
||||
viewportConsole = UI.ViewportWindow {
|
||||
y = 8,
|
||||
height = UI.term.height - 8,
|
||||
backgroundColor = colors.brown,
|
||||
},
|
||||
statusBar = UI.StatusBar {
|
||||
status = 'q to return',
|
||||
},
|
||||
accelerators = {
|
||||
q = 'back',
|
||||
backspace = 'back',
|
||||
},
|
||||
}
|
||||
|
||||
function methodsPage:enable(p)
|
||||
|
||||
self.peripheral = p or self.peripheral
|
||||
|
||||
local p = peripheral.wrap(self.peripheral.side)
|
||||
if p.getDocs then
|
||||
self.grid.values = { }
|
||||
for k,v in pairs(p.getDocs()) do
|
||||
table.insert(self.grid.values, {
|
||||
name = k,
|
||||
doc = v,
|
||||
})
|
||||
end
|
||||
elseif not p.getAdvancedMethodsData then
|
||||
self.grid.values = { }
|
||||
for name,f in pairs(p) do
|
||||
table.insert(self.grid.values, {
|
||||
name = name,
|
||||
noext = true,
|
||||
})
|
||||
end
|
||||
else
|
||||
self.grid.values = p.getAdvancedMethodsData()
|
||||
for name,f in pairs(self.grid.values) do
|
||||
f.name = name
|
||||
end
|
||||
end
|
||||
|
||||
self.viewportConsole.offy = 0
|
||||
|
||||
self.grid:update()
|
||||
self.grid:setIndex(1)
|
||||
|
||||
self.statusBar:setStatus(self.peripheral.type)
|
||||
UI.Page.enable(self)
|
||||
end
|
||||
|
||||
function methodsPage:eventHandler(event)
|
||||
if event.type == 'back' then
|
||||
UI:setPage(peripheralsPage)
|
||||
return true
|
||||
elseif event.type == 'grid_focus_row' then
|
||||
self.viewportConsole.offy = 0
|
||||
self.viewportConsole:draw()
|
||||
end
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
|
||||
function methodsPage.viewportConsole:draw()
|
||||
local c = self
|
||||
local method = methodsPage.grid:getSelected()
|
||||
|
||||
c:clear()
|
||||
c:setCursorPos(1, 1)
|
||||
|
||||
if method.noext then
|
||||
c.cursorY = 2
|
||||
c:print('No extended Information')
|
||||
return 2
|
||||
end
|
||||
|
||||
if method.doc then
|
||||
c:print(method.doc, nil, colors.yellow)
|
||||
c.ymax = c.cursorY + 1
|
||||
return
|
||||
end
|
||||
|
||||
if method.description then
|
||||
c:print(method.description)
|
||||
end
|
||||
|
||||
c.cursorY = c.cursorY + 2
|
||||
c.cursorX = 1
|
||||
|
||||
if method.returnTypes ~= '()' then
|
||||
c:print(method.returnTypes .. ' ', nil, colors.yellow)
|
||||
end
|
||||
c:print(method.name, nil, colors.black)
|
||||
c:print('(')
|
||||
|
||||
local maxArgLen = 1
|
||||
|
||||
for k,arg in ipairs(method.args) do
|
||||
if #arg.description > 0 then
|
||||
maxArgLen = math.max(#arg.name, maxArgLen)
|
||||
end
|
||||
local argName = arg.name
|
||||
local fg = colors.green
|
||||
if arg.optional then
|
||||
argName = string.format('[%s]', arg.name)
|
||||
fg = colors.orange
|
||||
end
|
||||
c:print(argName, nil, fg)
|
||||
if k < #method.args then
|
||||
c:print(', ')
|
||||
end
|
||||
end
|
||||
c:print(')')
|
||||
|
||||
c.cursorY = c.cursorY + 1
|
||||
|
||||
if #method.args > 0 then
|
||||
for _,arg in ipairs(method.args) do
|
||||
if #arg.description > 0 then
|
||||
c.cursorY = c.cursorY + 1
|
||||
c.cursorX = 1
|
||||
local fg = colors.green
|
||||
if arg.optional then
|
||||
fg = colors.orange
|
||||
end
|
||||
c:print(arg.name .. ': ', nil, fg)
|
||||
c.cursorX = maxArgLen + 3
|
||||
c:print(arg.description, nil, nil, maxArgLen + 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
c.ymax = c.cursorY + 1
|
||||
end
|
||||
|
||||
Event.on('peripheral', function()
|
||||
peripheralsPage:updatePeripherals()
|
||||
end)
|
||||
|
||||
Event.on('peripheral_detach', function()
|
||||
peripheralsPage:updatePeripherals()
|
||||
end)
|
||||
|
||||
UI:setPage(peripheralsPage)
|
||||
|
||||
UI:setPages({
|
||||
methods = methodsPage,
|
||||
})
|
||||
|
||||
UI:pullEvents()
|
@ -1,563 +0,0 @@
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Config = require('config')
|
||||
local Event = require('event')
|
||||
local Socket = require('socket')
|
||||
local UI = require('ui')
|
||||
local Util = require('util')
|
||||
|
||||
local GROUPS_PATH = 'usr/groups'
|
||||
local SCRIPTS_PATH = 'usr/etc/scripts'
|
||||
|
||||
multishell.setTitle(multishell.getCurrent(), 'Script')
|
||||
UI:configure('script', ...)
|
||||
|
||||
local config = {
|
||||
showGroups = false,
|
||||
variables = [[{
|
||||
COMPUTER_ID = os.getComputerID(),
|
||||
}]],
|
||||
}
|
||||
|
||||
Config.load('script', config)
|
||||
|
||||
local width = math.floor(UI.term.width / 2) - 1
|
||||
if UI.term.width % 2 ~= 0 then
|
||||
width = width + 1
|
||||
end
|
||||
|
||||
function processVariables(script)
|
||||
|
||||
local fn = loadstring('return ' .. config.variables)
|
||||
if fn then
|
||||
local variables = fn()
|
||||
|
||||
for k,v in pairs(variables) do
|
||||
local token = string.format('{%s}', k)
|
||||
script = script:gsub(token, v)
|
||||
end
|
||||
end
|
||||
return script
|
||||
end
|
||||
|
||||
function invokeScript(computer, scriptName)
|
||||
|
||||
local script = Util.readFile(scriptName)
|
||||
if not script then
|
||||
print('Unable to read script file')
|
||||
end
|
||||
|
||||
local socket = Socket.connect(computer.id, 161)
|
||||
if not socket then
|
||||
print('Unable to connect to ' .. computer.id)
|
||||
return
|
||||
end
|
||||
|
||||
script = processVariables(script)
|
||||
|
||||
Util.print('Running %s on %s', scriptName, computer.label)
|
||||
socket:write({ type = 'script', args = script })
|
||||
--[[
|
||||
local response = socket:read(2)
|
||||
|
||||
if response and response.result then
|
||||
if type(response.result) == 'table' then
|
||||
print(textutils.serialize(response.result))
|
||||
else
|
||||
print(tostring(response.result))
|
||||
end
|
||||
else
|
||||
printError('No response')
|
||||
end
|
||||
--]]
|
||||
|
||||
socket:close()
|
||||
end
|
||||
|
||||
function runScript(computerOrGroup, scriptName)
|
||||
if computerOrGroup.id then
|
||||
invokeScript(computerOrGroup, scriptName)
|
||||
else
|
||||
local list = computerOrGroup.list
|
||||
if computerOrGroup.path then
|
||||
list = Util.readTable(computerOrGroup.path)
|
||||
end
|
||||
if list then
|
||||
for _,computer in pairs(list) do
|
||||
invokeScript(computer, scriptName)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getActiveComputers(t)
|
||||
t = t or { }
|
||||
Util.clear(t)
|
||||
for k,computer in pairs(_G.network) do
|
||||
if computer.active then
|
||||
t[k] = computer
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function getTurtleList()
|
||||
local turtles = {
|
||||
label = 'Turtles',
|
||||
list = { },
|
||||
}
|
||||
for k,computer in pairs(getActiveComputers()) do
|
||||
if computer.fuel then
|
||||
turtles.list[k] = computer
|
||||
end
|
||||
end
|
||||
return turtles
|
||||
end
|
||||
|
||||
local args = { ... }
|
||||
if #args == 2 then
|
||||
local key = args[1]
|
||||
local script = args[2]
|
||||
local target
|
||||
if tonumber(key) then
|
||||
target = _G.network[tonumber(key)]
|
||||
elseif key == 'All' then
|
||||
target = {
|
||||
list = Util.shallowCopy(getActiveComputers()),
|
||||
}
|
||||
elseif key == 'Localhost' then
|
||||
target = { id = os.getComputerID() }
|
||||
elseif key == 'Turtles' then
|
||||
target = getTurtleList()
|
||||
else
|
||||
target = Util.readTable(fs.combine(GROUPS_PATH, key))
|
||||
end
|
||||
|
||||
if not target then
|
||||
error('Syntax: Script <ID or group> <script>')
|
||||
end
|
||||
|
||||
runScript(target, fs.combine(SCRIPTS_PATH, script))
|
||||
return
|
||||
end
|
||||
|
||||
local function getListing(t, path)
|
||||
Util.clear(t)
|
||||
local files = fs.list(path)
|
||||
for _,f in pairs(files) do
|
||||
table.insert(t, { label = f, path = fs.combine(path, f) })
|
||||
end
|
||||
end
|
||||
|
||||
local mainPage = UI.Page({
|
||||
menuBar = UI.MenuBar({
|
||||
buttons = {
|
||||
{ text = 'Groups', event = 'groups' },
|
||||
{ text = 'Scripts', event = 'scripts' },
|
||||
{ text = 'Toggle', event = 'toggle' },
|
||||
},
|
||||
}),
|
||||
computers = UI.ScrollingGrid({
|
||||
y = 2,
|
||||
height = UI.term.height-3,
|
||||
columns = {
|
||||
{ heading = 'Label', key = 'label', width = width },
|
||||
},
|
||||
width = width,
|
||||
sortColumn = 'label',
|
||||
}),
|
||||
scripts = UI.ScrollingGrid({
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'label', width = width },
|
||||
},
|
||||
sortColumn = 'label',
|
||||
height = UI.term.height - 3,
|
||||
width = width,
|
||||
x = UI.term.width - width + 1,
|
||||
y = 2,
|
||||
}),
|
||||
statusBar = UI.StatusBar({
|
||||
columns = {
|
||||
{ '', 'status', 4 },
|
||||
{ '', 'fuelF', 5 },
|
||||
{ '', 'distanceF', 4 },
|
||||
},
|
||||
autospace = true,
|
||||
}),
|
||||
accelerators = {
|
||||
q = 'quit',
|
||||
},
|
||||
})
|
||||
|
||||
local editorPage = UI.Page({
|
||||
menuBar = UI.MenuBar({
|
||||
showBackButton = true,
|
||||
buttons = {
|
||||
{ text = 'Save', event = 'save', help = 'Save this group' },
|
||||
},
|
||||
}),
|
||||
grid1 = UI.ScrollingGrid({
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'label', width = width },
|
||||
},
|
||||
sortColumn = 'label',
|
||||
height = UI.term.height - 4,
|
||||
width = width,
|
||||
y = 3,
|
||||
}),
|
||||
right = UI.Button({
|
||||
text = '>',
|
||||
event = 'right',
|
||||
x = width - 2,
|
||||
y = 2,
|
||||
width = 3,
|
||||
}),
|
||||
left = UI.Button({
|
||||
text = '<',
|
||||
event = 'left',
|
||||
x = UI.term.width - width + 1,
|
||||
y = 2,
|
||||
width = 3,
|
||||
}),
|
||||
grid2 = UI.ScrollingGrid({
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'label', width = width },
|
||||
},
|
||||
sortColumn = 'label',
|
||||
height = UI.term.height - 4,
|
||||
width = width,
|
||||
x = UI.term.width - width + 1,
|
||||
y = 3,
|
||||
}),
|
||||
statusBar = UI.StatusBar(),
|
||||
accelerators = {
|
||||
q = 'back',
|
||||
},
|
||||
})
|
||||
|
||||
local groupsPage = UI.Page({
|
||||
menuBar = UI.MenuBar({
|
||||
showBackButton = true,
|
||||
buttons = {
|
||||
{ text = 'Add', event = 'add' },
|
||||
{ text = 'Edit', event = 'edit' },
|
||||
{ text = 'Delete', event = 'delete' },
|
||||
},
|
||||
}),
|
||||
grid = UI.ScrollingGrid({
|
||||
y = 2,
|
||||
height = UI.term.height-2,
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'label' },
|
||||
},
|
||||
sortColumn = 'label',
|
||||
autospace = true,
|
||||
}),
|
||||
statusBar = UI.StatusBar(),
|
||||
accelerators = {
|
||||
q = 'back',
|
||||
},
|
||||
})
|
||||
|
||||
local scriptsPage = UI.Page({
|
||||
menuBar = UI.MenuBar({
|
||||
showBackButton = true,
|
||||
buttons = {
|
||||
{ text = 'Add', event = 'add' },
|
||||
{ text = 'Edit', event = 'edit' },
|
||||
{ text = 'Delete', event = 'delete' },
|
||||
},
|
||||
}),
|
||||
grid = UI.ScrollingGrid({
|
||||
y = 2,
|
||||
height = UI.term.height-2,
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'label' },
|
||||
},
|
||||
sortColumn = 'label',
|
||||
autospace = true,
|
||||
}),
|
||||
statusBar = UI.StatusBar(),
|
||||
accelerators = {
|
||||
a = 'add',
|
||||
e = 'edit',
|
||||
delete = 'delete',
|
||||
q = 'back',
|
||||
},
|
||||
})
|
||||
|
||||
function editorPage:enable()
|
||||
self:focusFirst()
|
||||
|
||||
local groupPath = fs.combine(GROUPS_PATH, self.groupName)
|
||||
if fs.exists(groupPath) then
|
||||
self.grid1.values = Util.readTable(groupPath)
|
||||
else
|
||||
Util.clear(self.grid1.values)
|
||||
end
|
||||
self.grid1:update()
|
||||
UI.Page.enable(self)
|
||||
end
|
||||
|
||||
function editorPage.grid2:draw()
|
||||
|
||||
getActiveComputers(self.values)
|
||||
|
||||
for k in pairs(editorPage.grid1.values) do
|
||||
self.values[k] = nil
|
||||
end
|
||||
self:update()
|
||||
|
||||
UI.ScrollingGrid.draw(self)
|
||||
end
|
||||
|
||||
function editorPage:eventHandler(event)
|
||||
|
||||
if event.type == 'back' then
|
||||
UI:setPage(groupsPage)
|
||||
|
||||
elseif event.type == 'left' then
|
||||
local computer = self.grid2:getSelected()
|
||||
self.grid1.values[computer.id] = computer
|
||||
self.grid1:update()
|
||||
self.grid1:draw()
|
||||
self.grid2:draw()
|
||||
|
||||
elseif event.type == 'right' then
|
||||
local computer = self.grid1:getSelected()
|
||||
self.grid1.values[computer.id] = nil
|
||||
self.grid1:update()
|
||||
self.grid1:draw()
|
||||
self.grid2:draw()
|
||||
|
||||
elseif event.type == 'save' then
|
||||
Util.writeTable(fs.combine(GROUPS_PATH, self.groupName), self.grid1.values)
|
||||
UI:setPage(groupsPage)
|
||||
end
|
||||
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
|
||||
local function nameDialog(f)
|
||||
local dialog = UI.Dialog({
|
||||
-- x = (UI.term.width - 28) / 2,
|
||||
width = 22,
|
||||
title = 'Enter Name',
|
||||
form = UI.Form {
|
||||
x = 2, rex = -2, y = 2,
|
||||
textEntry = UI.TextEntry({ y = 3, width = 20, limit = 20 })
|
||||
},
|
||||
})
|
||||
|
||||
dialog.eventHandler = function(self, event)
|
||||
if event.type == 'form_complete' then
|
||||
local name = self.form.textEntry.value
|
||||
if name then
|
||||
f(name)
|
||||
else
|
||||
self.statusBar:timedStatus('Invalid Name', 3)
|
||||
end
|
||||
return true
|
||||
elseif event.type == 'form_cancel' or event.type == 'cancel' then
|
||||
UI:setPreviousPage()
|
||||
else
|
||||
return UI.Dialog.eventHandler(self, event)
|
||||
end
|
||||
end
|
||||
|
||||
dialog:setFocus(dialog.form.textEntry)
|
||||
UI:setPage(dialog)
|
||||
end
|
||||
|
||||
function groupsPage:draw()
|
||||
getListing(self.grid.values, GROUPS_PATH)
|
||||
self.grid:update()
|
||||
UI.Page.draw(self)
|
||||
end
|
||||
|
||||
function groupsPage:enable()
|
||||
self:focusFirst()
|
||||
UI.Page.enable(self)
|
||||
end
|
||||
|
||||
function groupsPage:eventHandler(event)
|
||||
|
||||
if event.type == 'back' then
|
||||
UI:setPage(mainPage)
|
||||
|
||||
elseif event.type == 'add' then
|
||||
nameDialog(function(name)
|
||||
editorPage.groupName = name
|
||||
UI:setPage(editorPage)
|
||||
end)
|
||||
|
||||
elseif event.type == 'delete' then
|
||||
fs.delete(fs.combine(GROUPS_PATH, self.grid:getSelected().label))
|
||||
self:draw()
|
||||
|
||||
elseif event.type == 'edit' then
|
||||
editorPage.groupName = self.grid:getSelected().label
|
||||
UI:setPage(editorPage)
|
||||
end
|
||||
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
|
||||
function scriptsPage:draw()
|
||||
getListing(self.grid.values, SCRIPTS_PATH)
|
||||
self.grid:update()
|
||||
UI.Page.draw(self)
|
||||
end
|
||||
|
||||
function scriptsPage:enable()
|
||||
self:focusFirst()
|
||||
UI.Page.enable(self)
|
||||
end
|
||||
|
||||
function scriptsPage:eventHandler(event)
|
||||
|
||||
if event.type == 'back' then
|
||||
UI:setPreviousPage()
|
||||
|
||||
elseif event.type == 'add' then
|
||||
nameDialog(function(name)
|
||||
shell.run('edit ' .. fs.combine(SCRIPTS_PATH, name))
|
||||
UI:setPreviousPage()
|
||||
end)
|
||||
|
||||
elseif event.type == 'edit' then
|
||||
local name = fs.combine(SCRIPTS_PATH, self.grid:getSelected().label)
|
||||
shell.run('edit ' .. name)
|
||||
self:draw()
|
||||
|
||||
elseif event.type == 'delete' then
|
||||
local name = fs.combine(SCRIPTS_PATH, self.grid:getSelected().label)
|
||||
fs.delete(name)
|
||||
self:draw()
|
||||
end
|
||||
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
|
||||
function mainPage:eventHandler(event)
|
||||
|
||||
if event.type == 'quit' then
|
||||
Event.exitPullEvents()
|
||||
|
||||
elseif event.type == 'groups' then
|
||||
UI:setPage(groupsPage)
|
||||
|
||||
elseif event.type == 'scripts' then
|
||||
UI:setPage(scriptsPage)
|
||||
|
||||
elseif event.type == 'toggle' then
|
||||
config.showGroups = not config.showGroups
|
||||
local text = 'Computers'
|
||||
if config.showGroups then
|
||||
text = 'Groups'
|
||||
end
|
||||
-- self.statusBar.toggleButton.text = text
|
||||
self:draw()
|
||||
|
||||
Config.update('script', config)
|
||||
|
||||
elseif event.type == 'grid_focus_row' then
|
||||
local computer = self.computers:getSelected()
|
||||
self.statusBar.values = { computer }
|
||||
self.statusBar:draw()
|
||||
|
||||
elseif event.type == 'grid_select' then
|
||||
|
||||
local script = self.scripts:getSelected()
|
||||
local computer = self.computers:getSelected()
|
||||
|
||||
self:clear()
|
||||
self:sync()
|
||||
self.enabled = false
|
||||
runScript(computer, script.path)
|
||||
print()
|
||||
print('Press any key to continue...')
|
||||
while true do
|
||||
local e = os.pullEvent()
|
||||
if e == 'char' or e == 'key' or e == 'mouse_click' then
|
||||
break
|
||||
end
|
||||
end
|
||||
self.enabled = true
|
||||
self:draw()
|
||||
end
|
||||
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
|
||||
function mainPage.statusBar:draw()
|
||||
local computer = self.values[1]
|
||||
if computer then
|
||||
if computer.fuel then
|
||||
computer.fuelF = string.format("%dk", math.floor(computer.fuel/1000))
|
||||
end
|
||||
if computer.distance then
|
||||
computer.distanceF = Util.round(computer.distance, 1)
|
||||
end
|
||||
mainPage.statusBar:adjustWidth()
|
||||
end
|
||||
UI.StatusBar.draw(self)
|
||||
end
|
||||
|
||||
function mainPage:draw()
|
||||
getListing(self.scripts.values, SCRIPTS_PATH)
|
||||
|
||||
if config.showGroups then
|
||||
getListing(self.computers.values, GROUPS_PATH)
|
||||
table.insert(self.computers.values, {
|
||||
label = 'All',
|
||||
list = getActiveComputers(),
|
||||
})
|
||||
table.insert(self.computers.values, getTurtleList())
|
||||
table.insert(self.computers.values, {
|
||||
label = 'Localhost',
|
||||
id = os.getComputerID(),
|
||||
})
|
||||
else
|
||||
getActiveComputers(self.computers.values)
|
||||
end
|
||||
self.scripts:update()
|
||||
self.computers:update()
|
||||
UI.Page.draw(self)
|
||||
end
|
||||
|
||||
if not fs.exists(SCRIPTS_PATH) then
|
||||
fs.makeDir(SCRIPTS_PATH)
|
||||
end
|
||||
|
||||
if not fs.exists(GROUPS_PATH) then
|
||||
fs.makeDir(GROUPS_PATH)
|
||||
end
|
||||
|
||||
Event.on('network_attach', function()
|
||||
if mainPage.enabled then
|
||||
mainPage:draw()
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('network_detach', function()
|
||||
if mainPage.enabled then
|
||||
mainPage:draw()
|
||||
end
|
||||
end)
|
||||
|
||||
Event.onInterval(1, function()
|
||||
if mainPage.enabled then
|
||||
local selected = mainPage.computers:getSelected()
|
||||
if selected then
|
||||
local computer = _G.network[selected.id]
|
||||
mainPage.statusBar.values = { computer }
|
||||
mainPage.statusBar:draw()
|
||||
mainPage:sync()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
UI:setPage(mainPage)
|
||||
UI:pullEvents()
|
||||
UI.term:reset()
|
@ -1,339 +0,0 @@
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Event = require('event')
|
||||
local itemDB = require('itemDB')
|
||||
local Socket = require('socket')
|
||||
local Terminal = require('terminal')
|
||||
local UI = require('ui')
|
||||
local Util = require('util')
|
||||
|
||||
multishell.setTitle(multishell.getCurrent(), 'Turtles')
|
||||
UI.Button.defaults.focusIndicator = ' '
|
||||
UI:configure('Turtles', ...)
|
||||
|
||||
local options = {
|
||||
turtle = { arg = 'i', type = 'number', value = -1,
|
||||
desc = 'Turtle ID' },
|
||||
tab = { arg = 's', type = 'string', value = 'turtles',
|
||||
desc = 'Selected tab to display' },
|
||||
help = { arg = 'h', type = 'flag', value = false,
|
||||
desc = 'Displays the options' },
|
||||
}
|
||||
|
||||
local SCRIPTS_PATH = 'usr/etc/scripts'
|
||||
|
||||
local nullTerm = Terminal.getNullTerm(term.current())
|
||||
local turtles = { }
|
||||
local socket
|
||||
local policies = {
|
||||
{ label = 'none' },
|
||||
{ label = 'digOnly' },
|
||||
{ label = 'attackOnly' },
|
||||
{ label = 'digAttack' },
|
||||
{ label = 'turtleSafe' },
|
||||
}
|
||||
|
||||
local page = UI.Page {
|
||||
--[[
|
||||
policy = UI.Chooser {
|
||||
x = 2, y = 8,
|
||||
choices = {
|
||||
{ name = ' None ', value = 'none' },
|
||||
{ name = ' Safe ', value = 'turtleSafe' },
|
||||
},
|
||||
},
|
||||
]]
|
||||
coords = UI.Window {
|
||||
x = 2, y = 2, height = 3, rex = -2,
|
||||
},
|
||||
tabs = UI.Tabs {
|
||||
x = 1, y = 5, rey = -2,
|
||||
scripts = UI.Grid {
|
||||
tabTitle = 'Run',
|
||||
backgroundColor = UI.TabBar.defaults.selectedBackgroundColor,
|
||||
columns = {
|
||||
{ heading = '', key = 'label' },
|
||||
},
|
||||
disableHeader = true,
|
||||
sortColumn = 'label',
|
||||
autospace = true,
|
||||
},
|
||||
turtles = UI.Grid {
|
||||
tabTitle = 'Sel',
|
||||
backgroundColor = UI.TabBar.defaults.selectedBackgroundColor,
|
||||
columns = {
|
||||
{ heading = 'label', key = 'label' },
|
||||
{ heading = 'Dist', key = 'distance' },
|
||||
{ heading = 'Status', key = 'status' },
|
||||
{ heading = 'Fuel', key = 'fuel' },
|
||||
},
|
||||
disableHeader = true,
|
||||
sortColumn = 'label',
|
||||
autospace = true,
|
||||
},
|
||||
inventory = UI.Grid {
|
||||
backgroundColor = UI.TabBar.defaults.selectedBackgroundColor,
|
||||
tabTitle = 'Inv',
|
||||
columns = {
|
||||
{ heading = '', key = 'index', width = 2 },
|
||||
{ heading = '', key = 'qty', width = 2 },
|
||||
{ heading = 'Inventory', key = 'id', width = UI.term.width - 7 },
|
||||
},
|
||||
disableHeader = true,
|
||||
sortColumn = 'index',
|
||||
},
|
||||
policy = UI.Grid {
|
||||
tabTitle = 'Mod',
|
||||
backgroundColor = UI.TabBar.defaults.selectedBackgroundColor,
|
||||
columns = {
|
||||
{ heading = 'label', key = 'label' },
|
||||
},
|
||||
values = policies,
|
||||
disableHeader = true,
|
||||
sortColumn = 'label',
|
||||
autospace = true,
|
||||
},
|
||||
action = UI.Window {
|
||||
tabTitle = 'Act',
|
||||
moveUp = UI.Button {
|
||||
x = 5, y = 2,
|
||||
text = '/\\',
|
||||
fn = 'turtle.up',
|
||||
},
|
||||
moveDown = UI.Button {
|
||||
x = 5, y = 4,
|
||||
text = '\\/',
|
||||
fn = 'turtle.down',
|
||||
},
|
||||
moveForward = UI.Button {
|
||||
x = 9, y = 3,
|
||||
text = '>',
|
||||
fn = 'turtle.forward',
|
||||
},
|
||||
moveBack = UI.Button {
|
||||
x = 2, y = 3,
|
||||
text = '<',
|
||||
fn = 'turtle.back',
|
||||
},
|
||||
turnLeft = UI.Button {
|
||||
x = 2, y = 6,
|
||||
text = '<-',
|
||||
fn = 'turtle.turnLeft',
|
||||
},
|
||||
turnRight = UI.Button {
|
||||
x = 8, y = 6,
|
||||
text = '->',
|
||||
fn = 'turtle.turnRight',
|
||||
},
|
||||
},
|
||||
},
|
||||
statusBar = UI.StatusBar(),
|
||||
notification = UI.Notification(),
|
||||
accelerators = {
|
||||
q = 'quit',
|
||||
},
|
||||
}
|
||||
|
||||
function page:enable(turtle)
|
||||
self.turtle = turtle
|
||||
UI.Page.enable(self)
|
||||
end
|
||||
|
||||
function page:runFunction(script, nowrap)
|
||||
if not socket then
|
||||
socket = Socket.connect(self.turtle.id, 161)
|
||||
if not socket then
|
||||
self.notification:error('Unable to connect')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if not nowrap then
|
||||
script = 'turtle.run(' .. script .. ')'
|
||||
end
|
||||
socket:write({ type = 'script', args = script })
|
||||
end
|
||||
|
||||
function page:runScript(scriptName)
|
||||
if self.turtle then
|
||||
self.notification:info('Connecting')
|
||||
self:sync()
|
||||
|
||||
local cmd = string.format('Script %d %s', self.turtle.id, scriptName)
|
||||
local ot = term.redirect(nullTerm)
|
||||
pcall(function() shell.run(cmd) end)
|
||||
term.redirect(ot)
|
||||
self.notification:success('Sent')
|
||||
end
|
||||
end
|
||||
|
||||
function page.coords:draw()
|
||||
local t = self.parent.turtle
|
||||
if t then
|
||||
self:clear()
|
||||
self:setCursorPos(1, 1)
|
||||
local ind = 'GPS'
|
||||
if not t.point.gps then
|
||||
ind = 'REL'
|
||||
end
|
||||
self:print(string.format('%s : %d,%d,%d\nFuel: %s\n',
|
||||
ind, t.point.x, t.point.y, t.point.z, Util.toBytes(t.fuel)))
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Inventory Tab ]]--
|
||||
function page.tabs.inventory:getRowTextColor(row, selected)
|
||||
if page.turtle and row.selected then
|
||||
return colors.yellow
|
||||
end
|
||||
return UI.Grid.getRowTextColor(self, row, selected)
|
||||
end
|
||||
|
||||
function page.tabs.inventory:draw()
|
||||
local t = page.turtle
|
||||
Util.clear(self.values)
|
||||
if t then
|
||||
for _,v in ipairs(t.inventory) do
|
||||
if v.qty > 0 then
|
||||
table.insert(self.values, v)
|
||||
if v.index == t.slotIndex then
|
||||
v.selected = true
|
||||
end
|
||||
if v.id then
|
||||
local item = itemDB:get({ v.id, v.dmg })
|
||||
if item then
|
||||
v.id = item.displayName
|
||||
else
|
||||
v.id = v.id:gsub('.*:(.*)', '%1')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self:adjustWidth()
|
||||
self:update()
|
||||
UI.Grid.draw(self)
|
||||
end
|
||||
|
||||
function page.tabs.inventory:eventHandler(event)
|
||||
if event.type == 'grid_select' then
|
||||
local fn = string.format('turtle.select(%d)', event.selected.index)
|
||||
page:runFunction(fn)
|
||||
else
|
||||
return UI.Grid.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function page.tabs.scripts:draw()
|
||||
|
||||
Util.clear(self.values)
|
||||
local files = fs.list(SCRIPTS_PATH)
|
||||
for f,path in pairs(files) do
|
||||
table.insert(self.values, { label = f, path = path })
|
||||
end
|
||||
self:update()
|
||||
UI.Grid.draw(self)
|
||||
end
|
||||
|
||||
function page.tabs.scripts:eventHandler(event)
|
||||
if event.type == 'grid_select' then
|
||||
page:runScript(event.selected.label)
|
||||
else
|
||||
return UI.Grid.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function page.tabs.turtles:getDisplayValues(row)
|
||||
row = Util.shallowCopy(row)
|
||||
if row.fuel then
|
||||
row.fuel = Util.toBytes(row.fuel)
|
||||
end
|
||||
if row.distance then
|
||||
row.distance = Util.round(row.distance, 1)
|
||||
end
|
||||
return row
|
||||
end
|
||||
|
||||
function page.tabs.turtles:draw()
|
||||
Util.clear(self.values)
|
||||
for _,v in pairs(network) do
|
||||
if v.fuel then
|
||||
table.insert(self.values, v)
|
||||
end
|
||||
end
|
||||
self:update()
|
||||
UI.Grid.draw(self)
|
||||
end
|
||||
|
||||
function page.tabs.turtles:eventHandler(event)
|
||||
if event.type == 'grid_select' then
|
||||
page.turtle = event.selected
|
||||
if socket then
|
||||
socket:close()
|
||||
socket = nil
|
||||
end
|
||||
else
|
||||
return UI.Grid.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function page.statusBar:draw()
|
||||
local t = self.parent.turtle
|
||||
if t then
|
||||
local status = string.format('%s [ %s ]', t.status, Util.round(t.distance, 2))
|
||||
self:setStatus(status, true)
|
||||
end
|
||||
UI.StatusBar.draw(self)
|
||||
end
|
||||
|
||||
function page:eventHandler(event)
|
||||
if event.type == 'quit' then
|
||||
UI:exitPullEvents()
|
||||
elseif event.type == 'button_press' then
|
||||
if event.button.fn then
|
||||
self:runFunction(event.button.fn, event.button.nowrap)
|
||||
elseif event.button.script then
|
||||
self:runScript(event.button.script)
|
||||
end
|
||||
else
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function page:enable()
|
||||
UI.Page.enable(self)
|
||||
-- self.tabs:activateTab(page.tabs.turtles)
|
||||
end
|
||||
|
||||
if not Util.getOptions(options, { ... }, true) then
|
||||
return
|
||||
end
|
||||
|
||||
if options.turtle.value >= 0 then
|
||||
for i = 1, 10 do
|
||||
page.turtle = _G.network[options.turtle.value]
|
||||
if page.turtle then
|
||||
break
|
||||
end
|
||||
os.sleep(1)
|
||||
end
|
||||
end
|
||||
|
||||
Event.onInterval(1, function()
|
||||
if page.turtle then
|
||||
local t = _G.network[page.turtle.id]
|
||||
page.turtle = t
|
||||
page:draw()
|
||||
page:sync()
|
||||
end
|
||||
end)
|
||||
|
||||
UI:setPage(page)
|
||||
|
||||
page.tabs:activateTab(page.tabs[options.tab.value])
|
||||
|
||||
UI:pullEvents()
|
@ -1,24 +0,0 @@
|
||||
local args = { ... }
|
||||
if #args < 1 then
|
||||
error('cat <filename>')
|
||||
end
|
||||
|
||||
local fileName = shell.resolve(args[1])
|
||||
if not fs.exists(fileName) then
|
||||
error('not a file: ' .. args[1])
|
||||
end
|
||||
|
||||
local file = fs.open(fileName, 'r')
|
||||
if not file then
|
||||
error('unable to open ' .. args[1])
|
||||
end
|
||||
|
||||
while true do
|
||||
local line = file.readLine()
|
||||
if not line then
|
||||
break
|
||||
end
|
||||
print(line)
|
||||
end
|
||||
|
||||
file.close()
|
1275
sys/apps/edit.lua
1275
sys/apps/edit.lua
File diff suppressed because it is too large
Load Diff
@ -1,52 +0,0 @@
|
||||
local args = {...}
|
||||
|
||||
if not args[1] then
|
||||
print("Usage:")
|
||||
print(shell.getRunningProgram() .. " <program> [program arguments, ...]")
|
||||
return
|
||||
end
|
||||
|
||||
local path = shell.resolveProgram(args[1]) or shell.resolve(args[1])
|
||||
|
||||
-- here be dragons
|
||||
if fs.exists(path) then
|
||||
local eshell = setmetatable({getRunningProgram=function() return path end}, {__index = shell})
|
||||
local env = setmetatable({shell=eshell}, {__index=_ENV})
|
||||
|
||||
local f = fs.open(path, "r")
|
||||
local d = f.readAll()
|
||||
f.close()
|
||||
|
||||
local func, e = load(d, fs.getName(path), nil, env)
|
||||
if not func then
|
||||
printError("Syntax error:")
|
||||
printError(" " .. e)
|
||||
else
|
||||
table.remove(args, 1)
|
||||
xpcall(function() func(unpack(args)) end, function(err)
|
||||
local trace = {}
|
||||
local i, hitEnd, _, e = 4, false
|
||||
repeat
|
||||
_, e = pcall(function() error("<tracemarker>", i) end)
|
||||
i = i + 1
|
||||
if e == "xpcall: <tracemarker>" then
|
||||
hitEnd = true
|
||||
break
|
||||
end
|
||||
table.insert(trace, e)
|
||||
until i > 10
|
||||
table.remove(trace)
|
||||
if err:match("^" .. trace[1]:match("^(.-:%d+)")) then table.remove(trace, 1) end
|
||||
printError("\nProgram has crashed! Stack trace:")
|
||||
printError(err)
|
||||
for i, v in ipairs(trace) do
|
||||
printError(" at " .. v:match("^(.-:%d+)"))
|
||||
end
|
||||
if not hitEnd then
|
||||
printError(" ...")
|
||||
end
|
||||
end)
|
||||
end
|
||||
else
|
||||
printError("program not found")
|
||||
end
|
@ -1,2 +0,0 @@
|
||||
local options = table.concat({ ... }, ' ')
|
||||
shell.run('pastebin run sj4VMVJj ' .. options)
|
@ -1,53 +0,0 @@
|
||||
local args = { ... }
|
||||
local GIT_USER = 'kepler155c'
|
||||
local GIT_REPO = 'opus'
|
||||
local GIT_BRANCH = 'develop'
|
||||
local BASE = 'https://raw.githubusercontent.com/kepler155c/opus/develop/'
|
||||
|
||||
local function dourl(env, url)
|
||||
local h = http.get(url)
|
||||
if h then
|
||||
local fn, m = load(h.readAll(), url, nil, env)
|
||||
h.close()
|
||||
if fn then
|
||||
return fn()
|
||||
end
|
||||
end
|
||||
error('Failed to download ' .. url)
|
||||
end
|
||||
|
||||
local s, m = pcall(function()
|
||||
|
||||
_G.requireInjector = dourl(getfenv(1), BASE .. 'sys/apis/injector.lua')
|
||||
|
||||
local function mkenv()
|
||||
local env = { }
|
||||
for k,v in pairs(getfenv(1)) do
|
||||
env[k] = v
|
||||
end
|
||||
setmetatable(env, { __index = _G })
|
||||
return env
|
||||
end
|
||||
|
||||
-- install vfs
|
||||
dourl(mkenv(), BASE .. 'sys/extensions/vfs.lua')
|
||||
|
||||
-- install filesystem
|
||||
fs.mount('', 'gitfs', GIT_USER, GIT_REPO, GIT_BRANCH)
|
||||
|
||||
-- start program
|
||||
local file = table.remove(args, 1)
|
||||
|
||||
local s, m = os.run(mkenv(), file or 'startup', unpack(args))
|
||||
if not s and m then
|
||||
error(m)
|
||||
end
|
||||
end)
|
||||
|
||||
if not s and m then
|
||||
printError(m)
|
||||
end
|
||||
|
||||
if fs.restore then
|
||||
fs.restore()
|
||||
end
|
@ -25,7 +25,7 @@ if mounts then
|
||||
end
|
||||
end
|
||||
|
||||
fs.mount('usr', 'gitfs', 'kepler155c', 'opus-apps', 'develop')
|
||||
fs.mount('usr', 'gitfs', 'kepler155c/opus-apps/develop')
|
||||
|
||||
-- user environment
|
||||
if not fs.exists('usr/apps') then
|
||||
|
@ -6,7 +6,6 @@
|
||||
\030f \0304 \0307 \030 \031f)",
|
||||
title = "Network",
|
||||
run = "Network.lua",
|
||||
requires = "wireless_modem",
|
||||
},
|
||||
[ "90ef98d4b6fd15466f0a1f212ec1db8d9ebe018c" ] = {
|
||||
title = "Turtles",
|
||||
@ -55,7 +54,6 @@
|
||||
\0300\0317retu",
|
||||
title = "Scripts",
|
||||
run = "Script.lua",
|
||||
requires = "wireless_modem",
|
||||
},
|
||||
db56e2e1db9f7accfc37f2b132d27505c66ba521 = {
|
||||
title = "Adventure",
|
||||
@ -71,7 +69,7 @@
|
||||
icon = "\0301\03171\03180\030 \031 \
|
||||
\0301\03181\030 \031 \
|
||||
\0301\03170\03180\03171\0307\031f>",
|
||||
run = "update.lua",
|
||||
run = "http://pastebin.com/raw/sj4VMVJj",
|
||||
},
|
||||
[ "7ef35cac539f84722b0a988caee03b2df734c56a" ] = {
|
||||
title = "AppStore",
|
||||
@ -88,6 +86,7 @@
|
||||
\0304\031f _ \030 \031c/\0315\\\
|
||||
\0304 ",
|
||||
run = "simpleMiner.lua",
|
||||
requires = 'turtle',
|
||||
},
|
||||
c47ae15370cfe1ed2781eedc1dc2547d12d9e972 = {
|
||||
title = "Help",
|
||||
@ -128,6 +127,7 @@
|
||||
\0309 \0302 \0301 \
|
||||
\030e \0309 \0301 ",
|
||||
run = "rom/programs/pocket/falling",
|
||||
requires = 'advancedPocket',
|
||||
},
|
||||
bc0792d8dc81e8aa30b987246a5ce97c40cd6833 = {
|
||||
title = "System",
|
||||
@ -143,7 +143,8 @@
|
||||
icon = "\0307 \
|
||||
\0307 \0308\0311 \0305 \0308\031 \0307 \0308 \0301 \
|
||||
\0307 ",
|
||||
run = "storageManager.lua",
|
||||
run = "chestManager.lua",
|
||||
requires = 'turtle',
|
||||
},
|
||||
c5497bca58468ae64aed6c0fd921109217988db3 = {
|
||||
title = "Events",
|
||||
@ -216,6 +217,7 @@
|
||||
\030e\031c###\0308\0317=\030e\031c#\
|
||||
\030e\031c#\0307\031f.\030e\031c###",
|
||||
run = "usr/apps/builder.lua",
|
||||
requires = "turtle",
|
||||
},
|
||||
[ "d8c298dd41e4a4ec20e8307901797b64688b3b77" ] = {
|
||||
title = "GPS Deploy",
|
||||
@ -234,6 +236,7 @@
|
||||
title = "Micropaint",
|
||||
category = "Apps",
|
||||
run = "http://pastebin.com/raw/tMRzJXx2",
|
||||
requires = "advancedComputer",
|
||||
},
|
||||
[ "d78f28759f255a0db76604ee560b87c4715a0da5" ] = {
|
||||
apptype = "url",
|
||||
|
2108
sys/etc/recipes.db
Normal file
2108
sys/etc/recipes.db
Normal file
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
turtle.abortAction()
|
@ -1,113 +0,0 @@
|
||||
local function follow(id)
|
||||
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Event = require('event')
|
||||
local Point = require('point')
|
||||
local Socket = require('socket')
|
||||
|
||||
turtle.status = 'follow ' .. id
|
||||
|
||||
if not turtle.enableGPS() then
|
||||
error('turtle: No GPS found')
|
||||
end
|
||||
|
||||
local socket = Socket.connect(id, 161)
|
||||
if not socket then
|
||||
error('turtle: Unable to connect to ' .. id)
|
||||
return
|
||||
end
|
||||
|
||||
local lastPoint
|
||||
local following = false
|
||||
|
||||
Event.on('turtle_follow', function(_, pt)
|
||||
|
||||
local pts = {
|
||||
{ x = pt.x + 2, z = pt.z, y = pt.y },
|
||||
{ x = pt.x - 2, z = pt.z, y = pt.y },
|
||||
{ x = pt.x, z = pt.z + 2, y = pt.y },
|
||||
{ x = pt.x, z = pt.z - 2, y = pt.y },
|
||||
}
|
||||
|
||||
local cpt = Point.closest(turtle.point, pts)
|
||||
|
||||
local blocks = { }
|
||||
|
||||
local function addBlocks(tpt)
|
||||
table.insert(blocks, tpt)
|
||||
local apts = Point.adjacentPoints(tpt)
|
||||
for _,apt in pairs(apts) do
|
||||
table.insert(blocks, apt)
|
||||
end
|
||||
end
|
||||
|
||||
-- don't run into player
|
||||
addBlocks(pt)
|
||||
addBlocks({ x = pt.x, z = pt.z, y = pt.y + 1 })
|
||||
|
||||
if turtle.pathfind(cpt, { blocks = blocks }) then
|
||||
turtle.headTowards(pt)
|
||||
end
|
||||
following = false
|
||||
end)
|
||||
|
||||
Event.onInterval(.5, function()
|
||||
|
||||
local function getRemotePoint()
|
||||
if not turtle.abort then
|
||||
if socket:write({ type = 'gps' }) then
|
||||
return socket:read(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- sometimes gps will fail if moving
|
||||
local pt, d
|
||||
|
||||
for i = 1, 3 do
|
||||
pt, d = getRemotePoint()
|
||||
if pt then
|
||||
break
|
||||
end
|
||||
os.sleep(.5)
|
||||
end
|
||||
|
||||
if not pt or turtle.abort then
|
||||
error('Did not receive GPS location')
|
||||
end
|
||||
|
||||
if not lastPoint or (lastPoint.x ~= pt.x or lastPoint.y ~= pt.y or lastPoint.z ~= pt.z) then
|
||||
|
||||
if following then
|
||||
turtle.abort = true
|
||||
while following do
|
||||
os.sleep(.1)
|
||||
end
|
||||
turtle.abort = false
|
||||
end
|
||||
|
||||
-- check if gps is inaccurate (player moving too fast)
|
||||
if d < Point.pythagoreanDistance(turtle.point, pt) + 10 then
|
||||
lastPoint = Point.copy(pt)
|
||||
following = true
|
||||
os.queueEvent('turtle_follow', pt)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Event.on('turtle_abort', function()
|
||||
Event.exitPullEvents()
|
||||
end)
|
||||
|
||||
Event.pullEvents()
|
||||
|
||||
socket:close()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local s, m = turtle.run(function() follow({COMPUTER_ID}) end)
|
||||
if not s and m then
|
||||
error(m)
|
||||
end
|
@ -1 +0,0 @@
|
||||
turtle.run(turtle.gotoGPSHome)
|
@ -1,85 +0,0 @@
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Point = require('point')
|
||||
local Util = require('util')
|
||||
|
||||
local checkedNodes = { }
|
||||
local nodes = { }
|
||||
local box = { x = 65, ex = 69, y = 65, ey = 70, z = -23, ez = -19 }
|
||||
|
||||
local function inBox(pt, box)
|
||||
return pt.x >= box.x and
|
||||
pt.y >= box.y and
|
||||
pt.z >= box.z and
|
||||
pt.x <= box.ex and
|
||||
pt.y <= box.ey and
|
||||
pt.z <= box.ez
|
||||
end
|
||||
|
||||
local function toKey(pt)
|
||||
return table.concat({ pt.x, pt.y, pt.z }, ':')
|
||||
end
|
||||
|
||||
local function addNode(node)
|
||||
|
||||
for i = 0, 5 do
|
||||
local hi = turtle.getHeadingInfo(i)
|
||||
local testNode = { x = node.x + hi.xd, y = node.y + hi.yd, z = node.z + hi.zd }
|
||||
|
||||
if inBox(testNode, box) then
|
||||
local key = toKey(testNode)
|
||||
if not checkedNodes[key] then
|
||||
nodes[key] = testNode
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function dig(facing)
|
||||
local direction = facing
|
||||
if direction == 'forward' then
|
||||
direction = turtle.getHeadingInfo(turtle.point.heading).direction
|
||||
end
|
||||
local hi = turtle.getHeadingInfo(direction)
|
||||
local node = { x = turtle.point.x + hi.xd, y = turtle.point.y + hi.yd, z = turtle.point.z + hi.zd }
|
||||
if inBox(node, box) then
|
||||
if turtle.getAction(facing).dig() then
|
||||
addNode(node)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function level()
|
||||
repeat
|
||||
local node = { x = turtle.point.x, y = turtle.point.y, z = turtle.point.z }
|
||||
local key = toKey(node)
|
||||
|
||||
checkedNodes[key] = true
|
||||
nodes[key] = nil
|
||||
|
||||
dig('down')
|
||||
dig('up')
|
||||
dig('forward')
|
||||
|
||||
print(string.format('%d nodes remaining', Util.size(nodes)))
|
||||
|
||||
if Util.size(nodes) == 0 then
|
||||
break
|
||||
end
|
||||
|
||||
local node = Point.closest(turtle.point, nodes)
|
||||
if not turtle.gotoPoint(node) then
|
||||
break
|
||||
end
|
||||
until turtle.abort
|
||||
end
|
||||
|
||||
local pt = Util.shallowCopy(turtle.point)
|
||||
turtle.setPolicy(turtle.policies.none)
|
||||
if turtle.pathfind({ x = 65, y = 70, z = -23 }) then
|
||||
--turtle.reset()
|
||||
turtle.setPolicy(turtle.policies.digOnly)
|
||||
level()
|
||||
end
|
||||
turtle.pathfind(pt)
|
||||
--local s, m = turtle.run(level)
|
@ -1,29 +0,0 @@
|
||||
turtle.run(function()
|
||||
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local GPS = require('gps')
|
||||
local Socket = require('socket')
|
||||
|
||||
local id = {COMPUTER_ID}
|
||||
|
||||
if not turtle.enableGPS() then
|
||||
error('turtle: No GPS found')
|
||||
end
|
||||
|
||||
local socket = Socket.connect(id, 161)
|
||||
if not socket then
|
||||
error('turtle: Unable to connect to ' .. id)
|
||||
end
|
||||
|
||||
socket:write({ type = 'gps' })
|
||||
|
||||
local pt = socket:read(3)
|
||||
if not pt then
|
||||
error('turtle: No GPS response')
|
||||
end
|
||||
|
||||
if not turtle.pathfind(pt) then
|
||||
error('Unable to go to location')
|
||||
end
|
||||
end)
|
@ -1,102 +0,0 @@
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local Point = require('point')
|
||||
local Util = require('util')
|
||||
|
||||
local checkedNodes, nodes
|
||||
|
||||
local function addNode(node)
|
||||
|
||||
for i = 0, 3 do
|
||||
local hi = turtle.getHeadingInfo(i)
|
||||
local testNode = { x = node.x + hi.xd, z = node.z + hi.zd }
|
||||
|
||||
local key = table.concat({ testNode.x, testNode.z }, ':')
|
||||
if not checkedNodes[key] then
|
||||
nodes[key] = testNode
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function findObsidian()
|
||||
repeat
|
||||
local node = { x = turtle.point.x, z = turtle.point.z }
|
||||
local key = table.concat({ node.x, node.z }, ':')
|
||||
|
||||
checkedNodes[key] = true
|
||||
nodes[key] = nil
|
||||
|
||||
local _,b = turtle.inspectDown()
|
||||
if b and (b.name == 'minecraft:lava' or b.name == 'minecraft:flowing_lava') then
|
||||
if turtle.select('minecraft:water_bucket') then
|
||||
while true do
|
||||
if turtle.up() then
|
||||
break
|
||||
end
|
||||
print('stuck')
|
||||
end
|
||||
turtle.placeDown()
|
||||
os.sleep(2)
|
||||
turtle.placeDown()
|
||||
turtle.down()
|
||||
turtle.select(1)
|
||||
_, b = turtle.inspectDown()
|
||||
end
|
||||
end
|
||||
|
||||
if turtle.getCount(16) > 0 then
|
||||
print('Inventory full')
|
||||
print('Enter to continue...')
|
||||
read()
|
||||
end
|
||||
|
||||
if b and b.name == 'minecraft:obsidian' then
|
||||
turtle.digDown()
|
||||
addNode(node)
|
||||
else
|
||||
turtle.digDown()
|
||||
end
|
||||
|
||||
print(string.format('%d nodes remaining', Util.size(nodes)))
|
||||
|
||||
if Util.size(nodes) == 0 then
|
||||
break
|
||||
end
|
||||
|
||||
local node = Point.closest(turtle.point, nodes)
|
||||
if not turtle.gotoPoint(node) then
|
||||
break
|
||||
end
|
||||
until turtle.abort
|
||||
end
|
||||
|
||||
turtle.reset()
|
||||
turtle.setPolicy(turtle.policies.digOnly)
|
||||
local s, m = turtle.run(function()
|
||||
repeat
|
||||
|
||||
checkedNodes = { }
|
||||
nodes = { }
|
||||
|
||||
local _,b = turtle.inspectDown()
|
||||
if not b or b.name ~= 'minecraft:obsidian' then
|
||||
break
|
||||
end
|
||||
|
||||
findObsidian()
|
||||
if not turtle.select('minecraft:water_bucket') then
|
||||
break
|
||||
end
|
||||
turtle.goto(0, 0)
|
||||
turtle.placeDown()
|
||||
os.sleep(2)
|
||||
turtle.placeDown()
|
||||
turtle.down()
|
||||
turtle.select(1)
|
||||
until turtle.abort
|
||||
end)
|
||||
turtle.goto(0, 0, 0, 0)
|
||||
turtle.reset()
|
||||
if not s and m then
|
||||
error(m)
|
||||
end
|
@ -1 +0,0 @@
|
||||
os.reboot()
|
@ -1 +0,0 @@
|
||||
turtle.run(turtle.setGPSHome)
|
@ -1 +0,0 @@
|
||||
os.shutdown()
|
@ -1,74 +0,0 @@
|
||||
local function summon(id)
|
||||
|
||||
requireInjector(getfenv(1))
|
||||
|
||||
local GPS = require('gps')
|
||||
local Point = require('point')
|
||||
local Socket = require('socket')
|
||||
|
||||
turtle.status = 'GPSing'
|
||||
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 })
|
||||
|
||||
local pts = {
|
||||
[ 1 ] = { x = 0, z = 0, y = 0 },
|
||||
[ 2 ] = { x = 4, z = 0, y = 0 },
|
||||
[ 3 ] = { x = 2, z = -2, y = 2 },
|
||||
[ 4 ] = { x = 2, z = 2, y = 2 },
|
||||
}
|
||||
local tFixes = { }
|
||||
|
||||
local socket = Socket.connect(id, 161)
|
||||
|
||||
if not socket then
|
||||
error('turtle: Unable to connect to ' .. id)
|
||||
end
|
||||
|
||||
local function getDistance()
|
||||
socket:write({ type = 'ping' })
|
||||
local _, d = socket:read(5)
|
||||
return d
|
||||
end
|
||||
|
||||
local function doGPS()
|
||||
tFixes = { }
|
||||
for i = 1, 4 do
|
||||
if not turtle.gotoPoint(pts[i]) then
|
||||
error('turtle: Unable to perform GPS maneuver')
|
||||
end
|
||||
local distance = getDistance()
|
||||
if not distance then
|
||||
error('turtle: No response from ' .. id)
|
||||
end
|
||||
table.insert(tFixes, {
|
||||
position = vector.new(turtle.point.x, turtle.point.y, turtle.point.z),
|
||||
distance = distance
|
||||
})
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if not doGPS() then
|
||||
turtle.turnAround()
|
||||
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0})
|
||||
if not doGPS() then
|
||||
socket:close()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
socket:close()
|
||||
|
||||
local pos = GPS.trilaterate(tFixes)
|
||||
|
||||
if pos then
|
||||
local pt = { x = pos.x, y = pos.y, z = pos.z }
|
||||
local _, h = Point.calculateMoves(turtle.getPoint(), pt)
|
||||
local hi = turtle.getHeadingInfo(h)
|
||||
turtle.status = 'recalling'
|
||||
turtle.pathfind({ x = pt.x - hi.xd, z = pt.z - hi.zd, y = pt.y - hi.yd, heading = h })
|
||||
else
|
||||
error("turtle: Could not determine position")
|
||||
end
|
||||
end
|
||||
|
||||
turtle.run(function() summon({COMPUTER_ID}) end)
|
@ -1 +0,0 @@
|
||||
shell.run('/apps/update.lua')
|
Loading…
Reference in New Issue
Block a user