Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4cf76b8e8 | ||
|
|
44932ac515 | ||
|
|
f2b9efc80f | ||
|
|
c48243eae5 | ||
|
|
45bbc72fc3 | ||
|
|
aa50b55ab1 | ||
|
|
85c5f542a8 | ||
|
|
863b7ff600 | ||
|
|
0ce537d4ce | ||
|
|
73dc16703a | ||
|
|
f6fb6a4433 | ||
|
|
2526308eb6 | ||
|
|
d97a9d7468 | ||
|
|
9939c75fc3 | ||
|
|
77107e1d57 | ||
|
|
a2f452dc90 | ||
|
|
e0cac06c2a | ||
|
|
5e80591160 | ||
|
|
c057f98830 | ||
|
|
11a005969c | ||
|
|
6a1f72f957 | ||
|
|
3622518b20 | ||
|
|
1eb47cf3c8 | ||
|
|
7892c0dbb7 | ||
|
|
fe79e582cd | ||
|
|
a5c7fde530 | ||
|
|
c04ec356e5 | ||
|
|
194e6f0a91 | ||
|
|
d0c8d2dc4f | ||
|
|
728cda2215 | ||
|
|
1f31f7ef40 | ||
|
|
3734afed92 | ||
|
|
5232b5a115 | ||
|
|
f5dede540e | ||
|
|
980c635037 | ||
|
|
ed2d6eeef1 | ||
|
|
bba7841c43 | ||
|
|
8ef97df223 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/etc/fstab
|
/etc/fstab
|
||||||
|
/etc/recipes2.db
|
||||||
|
|||||||
@@ -6,42 +6,10 @@ local JSON = require('json')
|
|||||||
-- see https://github.com/Khroki/MCEdit-Unified/blob/master/pymclevel/minecraft.yaml
|
-- see https://github.com/Khroki/MCEdit-Unified/blob/master/pymclevel/minecraft.yaml
|
||||||
-- see https://github.com/Khroki/MCEdit-Unified/blob/master/Items/minecraft/blocks.json
|
-- see https://github.com/Khroki/MCEdit-Unified/blob/master/Items/minecraft/blocks.json
|
||||||
|
|
||||||
--[[-- nameDB --]]--
|
|
||||||
local nameDB = TableDB({
|
|
||||||
fileName = 'blocknames.db'
|
|
||||||
})
|
|
||||||
function nameDB:load(dir, blockDB)
|
|
||||||
self.fileName = fs.combine(dir, self.fileName)
|
|
||||||
if fs.exists(self.fileName) then
|
|
||||||
TableDB.load(self)
|
|
||||||
end
|
|
||||||
self.blockDB = blockDB
|
|
||||||
end
|
|
||||||
|
|
||||||
function nameDB:getName(id, dmg)
|
|
||||||
return self:lookupName(id, dmg) or id .. ':' .. dmg
|
|
||||||
end
|
|
||||||
|
|
||||||
function nameDB:lookupName(id, dmg)
|
|
||||||
-- is it in the name db ?
|
|
||||||
local name = self:get({ id, dmg })
|
|
||||||
if name then
|
|
||||||
return name
|
|
||||||
end
|
|
||||||
|
|
||||||
-- is it in the block db ?
|
|
||||||
for _,v in pairs(self.blockDB.data) do
|
|
||||||
if v.strId == id and v.dmg == dmg then
|
|
||||||
return v.name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[-- blockDB --]]--
|
--[[-- blockDB --]]--
|
||||||
local blockDB = TableDB()
|
local blockDB = TableDB()
|
||||||
|
|
||||||
function blockDB:load()
|
function blockDB:load()
|
||||||
|
|
||||||
local blocks = JSON.decodeFromFile('usr/etc/blocks.json')
|
local blocks = JSON.decodeFromFile('usr/etc/blocks.json')
|
||||||
|
|
||||||
if not blocks then
|
if not blocks then
|
||||||
@@ -85,19 +53,6 @@ end
|
|||||||
local placementDB = TableDB()
|
local placementDB = TableDB()
|
||||||
|
|
||||||
function placementDB:load(sbDB, btDB)
|
function placementDB:load(sbDB, btDB)
|
||||||
|
|
||||||
for k,blockType in pairs(sbDB.data) do
|
|
||||||
local bt = btDB.data[blockType]
|
|
||||||
if not bt then
|
|
||||||
error('missing block type: ' .. blockType)
|
|
||||||
end
|
|
||||||
local id, dmg = string.match(k, '(%d+):*(%d+)')
|
|
||||||
self:addSubsForBlockType(tonumber(id), tonumber(dmg), bt)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function placementDB:load2(sbDB, btDB)
|
|
||||||
|
|
||||||
for k,v in pairs(sbDB.data) do
|
for k,v in pairs(sbDB.data) do
|
||||||
if v.place then
|
if v.place then
|
||||||
local bt = btDB.data[v.place]
|
local bt = btDB.data[v.place]
|
||||||
@@ -113,7 +68,6 @@ function placementDB:load2(sbDB, btDB)
|
|||||||
self:addSubsForBlockType(155, 2, btDB.data['quartz-pillar'])
|
self:addSubsForBlockType(155, 2, btDB.data['quartz-pillar'])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function placementDB:addSubsForBlockType(id, dmg, bt)
|
function placementDB:addSubsForBlockType(id, dmg, bt)
|
||||||
for _,sub in pairs(bt) do
|
for _,sub in pairs(bt) do
|
||||||
local odmg = sub.odmg
|
local odmg = sub.odmg
|
||||||
@@ -178,7 +132,6 @@ function blockTypeDB:addTemp(blockType, subs)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function blockTypeDB:load()
|
function blockTypeDB:load()
|
||||||
|
|
||||||
blockTypeDB:addTemp('stairs', {
|
blockTypeDB:addTemp('stairs', {
|
||||||
{ 0, nil, 0, 'east-up' },
|
{ 0, nil, 0, 'east-up' },
|
||||||
{ 1, nil, 0, 'west-up' },
|
{ 1, nil, 0, 'west-up' },
|
||||||
@@ -564,20 +517,17 @@ end
|
|||||||
|
|
||||||
local Blocks = class()
|
local Blocks = class()
|
||||||
function Blocks:init(args)
|
function Blocks:init(args)
|
||||||
|
|
||||||
Util.merge(self, args)
|
Util.merge(self, args)
|
||||||
self.blockDB = blockDB
|
self.blockDB = blockDB
|
||||||
self.nameDB = nameDB
|
|
||||||
|
|
||||||
blockDB:load()
|
blockDB:load()
|
||||||
blockTypeDB:load()
|
blockTypeDB:load()
|
||||||
nameDB:load(self.dir, blockDB)
|
placementDB:load(blockDB, blockTypeDB)
|
||||||
placementDB:load2(blockDB, blockTypeDB)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- for an ID / dmg (with placement info) - return the correct block (without the placment info embedded in the dmg)
|
-- for an ID / dmg (with placement info)
|
||||||
|
-- return the correct block (without the placment info embedded in the dmg)
|
||||||
function Blocks:getPlaceableBlock(id, dmg)
|
function Blocks:getPlaceableBlock(id, dmg)
|
||||||
|
|
||||||
local p = placementDB:get({id, dmg})
|
local p = placementDB:get({id, dmg})
|
||||||
if p then
|
if p then
|
||||||
return Util.shallowCopy(p)
|
return Util.shallowCopy(p)
|
||||||
101
apis/builder/builder.lua
Normal file
101
apis/builder/builder.lua
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
local Blocks = require('builder.blocks')
|
||||||
|
local class = require('class')
|
||||||
|
local Message = require('message')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
|
local device = _G.device
|
||||||
|
local fs = _G.fs
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
|
local Builder = class()
|
||||||
|
Util.merge(Builder, {
|
||||||
|
isCommandComputer = not turtle,
|
||||||
|
loc = { },
|
||||||
|
index = 1,
|
||||||
|
mode = 'build',
|
||||||
|
})
|
||||||
|
|
||||||
|
local BUILDER_DIR = 'usr/builder'
|
||||||
|
|
||||||
|
local blockInfo = Blocks()
|
||||||
|
|
||||||
|
function Builder:getBlockCounts()
|
||||||
|
local blocks = { }
|
||||||
|
|
||||||
|
for k = self.index, #self.schematic.blocks do
|
||||||
|
local b = self.schematic.blocks[k]
|
||||||
|
local key = tostring(b.id) .. ':' .. b.dmg
|
||||||
|
local block = blocks[key]
|
||||||
|
if not block then
|
||||||
|
block = Util.shallowCopy(b)
|
||||||
|
block.qty = 0
|
||||||
|
block.need = 0
|
||||||
|
blocks[key] = block
|
||||||
|
end
|
||||||
|
block.need = block.need + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return blocks
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:substituteBlocks(throttle)
|
||||||
|
for _,b in pairs(self.schematic.blocks) do
|
||||||
|
|
||||||
|
-- replace schematic block type with substitution
|
||||||
|
local pb = blockInfo:getPlaceableBlock(b.id, b.dmg)
|
||||||
|
|
||||||
|
Util.merge(b, pb)
|
||||||
|
|
||||||
|
b.odmg = pb.odmg or pb.dmg
|
||||||
|
|
||||||
|
local sub = self.subDB:get({ b.id, b.dmg })
|
||||||
|
if sub then
|
||||||
|
b.id, b.dmg = self.subDB:extract(sub)
|
||||||
|
end
|
||||||
|
throttle()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:reloadSchematic(throttle)
|
||||||
|
self.schematic:reload(throttle)
|
||||||
|
self:substituteBlocks(throttle)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:log(...)
|
||||||
|
Util.print(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:dumpInventory()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:logBlock(index, b)
|
||||||
|
local bdir = b.direction or ''
|
||||||
|
local logText = string.format('%d %s:%d (x:%d,z:%d:y:%d) %s',
|
||||||
|
index, b.id, b.dmg, b.x, b.z, b.y, bdir)
|
||||||
|
self:log(logText)
|
||||||
|
-- self:log(b.index) -- unique identifier of block
|
||||||
|
|
||||||
|
if device.wireless_modem then
|
||||||
|
Message.broadcast('builder', { x = b.x, y = b.y, z = b.z, heading = b.heading })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:saveProgress(index)
|
||||||
|
Util.writeTable(
|
||||||
|
fs.combine(BUILDER_DIR, self.schematic.filename .. '.progress'),
|
||||||
|
{ index = index, loc = self.loc }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:loadProgress(filename)
|
||||||
|
local progress = Util.readTable(fs.combine(BUILDER_DIR, filename))
|
||||||
|
if progress then
|
||||||
|
self.index = progress.index
|
||||||
|
if self.index > #self.schematic.blocks then
|
||||||
|
self.index = 1
|
||||||
|
end
|
||||||
|
self.loc = progress.loc or { }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Builder
|
||||||
84
apis/builder/commands.lua
Normal file
84
apis/builder/commands.lua
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
local Builder = require('builder.builder')
|
||||||
|
local Event = require('event')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
|
local commands = _G.commands
|
||||||
|
local fs = _G.fs
|
||||||
|
local os = _G.os
|
||||||
|
local read = _G.read
|
||||||
|
|
||||||
|
function Builder:begin()
|
||||||
|
local direction = 1
|
||||||
|
local last = #self.schematic.blocks
|
||||||
|
local throttle = Util.throttle()
|
||||||
|
|
||||||
|
local cx, cy, cz = commands.getBlockPosition()
|
||||||
|
if self.loc.x then
|
||||||
|
cx, cy, cz = self.loc.rx, self.loc.ry, self.loc.rz
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.mode == 'destroy' then
|
||||||
|
direction = -1
|
||||||
|
last = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = self.index, last, direction do
|
||||||
|
self.index = i
|
||||||
|
|
||||||
|
local b = self.schematic:getComputedBlock(i)
|
||||||
|
|
||||||
|
if b.id ~= 'minecraft:air' then
|
||||||
|
|
||||||
|
self:logBlock(self.index, b)
|
||||||
|
|
||||||
|
local id = b.id
|
||||||
|
if self.mode == 'destroy' then
|
||||||
|
id = 'minecraft:air'
|
||||||
|
end
|
||||||
|
|
||||||
|
local function placeBlock(bid, dmg, x, y, z)
|
||||||
|
local command = table.concat({
|
||||||
|
"setblock",
|
||||||
|
cx + x + 1,
|
||||||
|
cy + y,
|
||||||
|
cz + z + 1,
|
||||||
|
bid,
|
||||||
|
dmg,
|
||||||
|
}, ' ')
|
||||||
|
|
||||||
|
commands.execAsync(command)
|
||||||
|
|
||||||
|
local result = { os.pullEvent("task_complete") }
|
||||||
|
if not result[4] then
|
||||||
|
Util.print(result[5])
|
||||||
|
if self.mode ~= 'destroy' then
|
||||||
|
read()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
placeBlock(id, b.odmg, b.x, b.y, b.z)
|
||||||
|
|
||||||
|
if b.twoHigh then
|
||||||
|
local _, topBlock = self.schematic:findIndexAt(b.x, b.z, b.y + 1, true)
|
||||||
|
if topBlock then
|
||||||
|
placeBlock(id, topBlock.odmg, b.x, b.y + 1, b.z)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.mode == 'destroy' then
|
||||||
|
self:saveProgress(math.max(self.index, 1))
|
||||||
|
else
|
||||||
|
self:saveProgress(self.index + 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
throttle() -- sleep in case there are a large # of skipped blocks
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.delete(self.schematic.filename .. '.progress')
|
||||||
|
print('Finished')
|
||||||
|
Event.exitPullEvents()
|
||||||
|
end
|
||||||
|
|
||||||
|
return Builder
|
||||||
@@ -1,9 +1,17 @@
|
|||||||
local class = require('class')
|
local class = require('class')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
local DEFLATE = require('deflatelua')
|
local DEFLATE = require('deflatelua')
|
||||||
local UI = require('ui')
|
|
||||||
local Point = require('point')
|
local Point = require('point')
|
||||||
|
|
||||||
|
local bit = _G.bit
|
||||||
|
local fs = _G.fs
|
||||||
|
local os = _G.os
|
||||||
|
local term = _G.term
|
||||||
|
|
||||||
|
local function getHeadingInfo(heading)
|
||||||
|
return Point.headings[heading]
|
||||||
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Loading and manipulating a schematic
|
Loading and manipulating a schematic
|
||||||
--]]
|
--]]
|
||||||
@@ -11,8 +19,54 @@ local Point = require('point')
|
|||||||
local schematicMagic = 0x0a00
|
local schematicMagic = 0x0a00
|
||||||
local gzipMagic = 0x1f8b
|
local gzipMagic = 0x1f8b
|
||||||
|
|
||||||
|
--[[-- Spinner --]]--
|
||||||
|
local Spinner = class()
|
||||||
|
function Spinner:init(args)
|
||||||
|
local defaults = {
|
||||||
|
timeout = .095,
|
||||||
|
c = os.clock(),
|
||||||
|
spinIndex = 0,
|
||||||
|
spinSymbols = { '-', '/', '|', '\\' }
|
||||||
|
}
|
||||||
|
defaults.x, defaults.y = term.getCursorPos()
|
||||||
|
defaults.startX = defaults.x
|
||||||
|
defaults.startY = defaults.y
|
||||||
|
|
||||||
|
Util.merge(self, defaults)
|
||||||
|
Util.merge(self, args)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Spinner:spin(text)
|
||||||
|
local cc = os.clock()
|
||||||
|
if text then
|
||||||
|
self.text = text
|
||||||
|
end
|
||||||
|
if cc > self.c + self.timeout then
|
||||||
|
term.setCursorPos(self.x, self.y)
|
||||||
|
local str = self.spinSymbols[self.spinIndex % #self.spinSymbols + 1]
|
||||||
|
if self.text then
|
||||||
|
str = str .. ' ' .. self.text
|
||||||
|
self.text = nil
|
||||||
|
end
|
||||||
|
term.write(str)
|
||||||
|
self.spinIndex = self.spinIndex + 1
|
||||||
|
os.sleep(0)
|
||||||
|
self.c = os.clock()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Spinner:stop(text)
|
||||||
|
term.setCursorPos(self.x, self.y)
|
||||||
|
local str = string.rep(' ', #self.spinSymbols)
|
||||||
|
if text then
|
||||||
|
str = str .. ' ' .. text
|
||||||
|
end
|
||||||
|
term.write(str)
|
||||||
|
term.setCursorPos(self.startX, self.startY)
|
||||||
|
end
|
||||||
|
|
||||||
local Schematic = class()
|
local Schematic = class()
|
||||||
function Schematic:init(args)
|
function Schematic:init()
|
||||||
self.blocks = { }
|
self.blocks = { }
|
||||||
self.damages = { }
|
self.damages = { }
|
||||||
self.originalBlocks = { }
|
self.originalBlocks = { }
|
||||||
@@ -48,7 +102,7 @@ function Schematic:readname(h)
|
|||||||
local n = n1*256 + n2
|
local n = n1*256 + n2
|
||||||
|
|
||||||
local str = ""
|
local str = ""
|
||||||
for i=1,n do
|
for _=1,n do
|
||||||
local c = h:readbyte(h)
|
local c = h:readbyte(h)
|
||||||
if c == nil then
|
if c == nil then
|
||||||
return
|
return
|
||||||
@@ -218,11 +272,11 @@ function DiskFile:close()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local MemoryFile = class()
|
local MemoryFile = class()
|
||||||
function MemoryFile:init(args)
|
function MemoryFile:init()
|
||||||
self.s = { }
|
self.s = { }
|
||||||
self.i = 1
|
self.i = 1
|
||||||
end
|
end
|
||||||
function MemoryFile:open(filename)
|
function MemoryFile:open()
|
||||||
self.i = 1
|
self.i = 1
|
||||||
end
|
end
|
||||||
function MemoryFile:close() end
|
function MemoryFile:close() end
|
||||||
@@ -247,7 +301,7 @@ function Schematic:decompress(ifname, spinner)
|
|||||||
local mh = MemoryFile()
|
local mh = MemoryFile()
|
||||||
|
|
||||||
DEFLATE.gunzip({
|
DEFLATE.gunzip({
|
||||||
input=function(...) spinner:spin() return ifh.read() end,
|
input=function() spinner:spin() return ifh.read() end,
|
||||||
output=function(b) mh:write(b) end,
|
output=function(b) mh:write(b) end,
|
||||||
disable_crc=true
|
disable_crc=true
|
||||||
})
|
})
|
||||||
@@ -276,7 +330,7 @@ function Schematic:loadpass(fh, spinner)
|
|||||||
|
|
||||||
fh:close()
|
fh:close()
|
||||||
|
|
||||||
print('Assigning coords ')
|
spinner.text = 'Assigning coords '
|
||||||
local index = 1
|
local index = 1
|
||||||
for _, b in ipairs(self.blocks) do
|
for _, b in ipairs(self.blocks) do
|
||||||
while index < b.index do
|
while index < b.index do
|
||||||
@@ -309,11 +363,10 @@ function Schematic:loadpass(fh, spinner)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Schematic:load(filename)
|
function Schematic:load(filename)
|
||||||
|
local _, cy = term.getCursorPos()
|
||||||
local cursorX, cursorY = term.getCursorPos()
|
local spinner = Spinner({
|
||||||
local spinner = UI.Spinner({
|
x = 1,
|
||||||
x = UI.term.width,
|
y = cy,
|
||||||
y = cursorY - 1
|
|
||||||
})
|
})
|
||||||
local f
|
local f
|
||||||
|
|
||||||
@@ -322,7 +375,7 @@ function Schematic:load(filename)
|
|||||||
filename = originalFile .. '.uncompressed'
|
filename = originalFile .. '.uncompressed'
|
||||||
|
|
||||||
if not fs.exists(filename) then
|
if not fs.exists(filename) then
|
||||||
print('Decompressing')
|
spinner.text = 'Decompressing'
|
||||||
f = self:decompress(originalFile, spinner)
|
f = self:decompress(originalFile, spinner)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -335,7 +388,7 @@ function Schematic:load(filename)
|
|||||||
|
|
||||||
self:checkFileType(f)
|
self:checkFileType(f)
|
||||||
|
|
||||||
print('Loading blocks ')
|
spinner.text = 'Loading blocks '
|
||||||
self:loadpass(f, spinner)
|
self:loadpass(f, spinner)
|
||||||
|
|
||||||
self.rowIndex = { }
|
self.rowIndex = { }
|
||||||
@@ -352,7 +405,7 @@ function Schematic:load(filename)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Schematic:assignDamages(spinner)
|
function Schematic:assignDamages(spinner)
|
||||||
print('Assigning damages')
|
spinner.text = 'Assigning damages'
|
||||||
|
|
||||||
for _,b in pairs(self.blocks) do
|
for _,b in pairs(self.blocks) do
|
||||||
b.dmg = self.damages[b.index] or 0
|
b.dmg = self.damages[b.index] or 0
|
||||||
@@ -382,7 +435,7 @@ function Schematic:findIndexAt(x, z, y, allBlocks)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Schematic:findBlockAtSide(b, side)
|
function Schematic:findBlockAtSide(b, side)
|
||||||
local hi = turtle.getHeadingInfo(side)
|
local hi = getHeadingInfo(side)
|
||||||
local index = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y + hi.yd)
|
local index = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y + hi.yd)
|
||||||
if index then
|
if index then
|
||||||
return self.blocks[index] -- could be better
|
return self.blocks[index] -- could be better
|
||||||
@@ -416,10 +469,10 @@ function Schematic:bestSide(b, chains, ...)
|
|||||||
local blocks = { }
|
local blocks = { }
|
||||||
|
|
||||||
for k,d in pairs(directions) do
|
for k,d in pairs(directions) do
|
||||||
local hi = turtle.getHeadingInfo(d)
|
local hi = getHeadingInfo(d)
|
||||||
local sb = self:findIndexAt(b.x - hi.xd, b.z - hi.zd, b.y)
|
local sb = self:findIndexAt(b.x - hi.xd, b.z - hi.zd, b.y)
|
||||||
if not sb then
|
if not sb then
|
||||||
b.heading = turtle.getHeadingInfo(d).heading
|
b.heading = getHeadingInfo(d).heading
|
||||||
b.direction = d .. '-block'
|
b.direction = d .. '-block'
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -476,7 +529,7 @@ function Schematic:bestFlipSide(b, chains)
|
|||||||
}
|
}
|
||||||
|
|
||||||
local d = directions[b.direction]
|
local d = directions[b.direction]
|
||||||
local hi = turtle.getHeadingInfo(d)
|
local hi = getHeadingInfo(d)
|
||||||
local _, fb = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y)
|
local _, fb = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y)
|
||||||
|
|
||||||
if fb then
|
if fb then
|
||||||
@@ -492,7 +545,7 @@ function Schematic:bestFlipSide(b, chains)
|
|||||||
{ x = b.x - hi.xd, z = b.z - hi.zd, y = b.y }, -- room for the turtle
|
{ x = b.x - hi.xd, z = b.z - hi.zd, y = b.y }, -- room for the turtle
|
||||||
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
|
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
|
||||||
})
|
})
|
||||||
b.direction = turtle.getHeadingInfo((hi.heading + 2) % 4).direction .. '-block'
|
b.direction = getHeadingInfo((hi.heading + 2) % 4).direction .. '-block'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -532,7 +585,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
|
|||||||
table.insert(pc, { x = b.x, z = b.z, y = b.y })
|
table.insert(pc, { x = b.x, z = b.z, y = b.y })
|
||||||
|
|
||||||
b.direction = side1 .. '-block'
|
b.direction = side1 .. '-block'
|
||||||
b.heading = turtle.getHeadingInfo(side1).heading
|
b.heading = getHeadingInfo(side1).heading
|
||||||
|
|
||||||
if b == lb then
|
if b == lb then
|
||||||
break
|
break
|
||||||
@@ -550,7 +603,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
|
|||||||
local ub = self:findBlockAtSide(fb, 'down')
|
local ub = self:findBlockAtSide(fb, 'down')
|
||||||
if not ub then
|
if not ub then
|
||||||
fb.direction = side1 .. '-block'
|
fb.direction = side1 .. '-block'
|
||||||
fb.heading = turtle.getHeadingInfo(side1).heading
|
fb.heading = getHeadingInfo(side1).heading
|
||||||
else
|
else
|
||||||
fb.direction = od
|
fb.direction = od
|
||||||
end
|
end
|
||||||
@@ -564,7 +617,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
|
|||||||
local ub = self:findBlockAtSide(lb, 'down')
|
local ub = self:findBlockAtSide(lb, 'down')
|
||||||
if not ub then
|
if not ub then
|
||||||
lb.direction = side1 .. '-block'
|
lb.direction = side1 .. '-block'
|
||||||
lb.heading = turtle.getHeadingInfo(side1).heading
|
lb.heading = getHeadingInfo(side1).heading
|
||||||
else
|
else
|
||||||
fb.direction = od
|
fb.direction = od
|
||||||
end
|
end
|
||||||
@@ -581,7 +634,7 @@ function Schematic:determineBlockPlacement(y)
|
|||||||
|
|
||||||
print('Processing level ' .. y)
|
print('Processing level ' .. y)
|
||||||
|
|
||||||
local spinner = UI.Spinner({
|
local spinner = Spinner({
|
||||||
x = 1,
|
x = 1,
|
||||||
spinSymbols = { 'o.....', '.o....', '..o...', '...o..', '....o.', '.....o' }
|
spinSymbols = { 'o.....', '.o....', '..o...', '...o..', '....o.', '.....o' }
|
||||||
})
|
})
|
||||||
@@ -709,12 +762,12 @@ function Schematic:determineBlockPlacement(y)
|
|||||||
spinner:spin(#dirtyBlocks + #dirtyBlocks2 .. ' blocks remaining ')
|
spinner:spin(#dirtyBlocks + #dirtyBlocks2 .. ' blocks remaining ')
|
||||||
|
|
||||||
if directions[d] then
|
if directions[d] then
|
||||||
b.heading = turtle.getHeadingInfo(directions[d]).heading
|
b.heading = getHeadingInfo(directions[d]).heading
|
||||||
end
|
end
|
||||||
|
|
||||||
if doorDirections[d] then
|
if doorDirections[d] then
|
||||||
|
|
||||||
local hi = turtle.getHeadingInfo(doorDirections[d])
|
local hi = getHeadingInfo(doorDirections[d])
|
||||||
b.heading = hi.heading
|
b.heading = hi.heading
|
||||||
|
|
||||||
self:addPlacementChain(chains, {
|
self:addPlacementChain(chains, {
|
||||||
@@ -726,9 +779,9 @@ function Schematic:determineBlockPlacement(y)
|
|||||||
if stairDownDirections[d] then
|
if stairDownDirections[d] then
|
||||||
if not self:findIndexAt(b.x, b.z, b.y-1) then
|
if not self:findIndexAt(b.x, b.z, b.y-1) then
|
||||||
b.direction = stairDownDirections[b.direction]
|
b.direction = stairDownDirections[b.direction]
|
||||||
b.heading = turtle.getHeadingInfo(b.direction).heading
|
b.heading = getHeadingInfo(b.direction).heading
|
||||||
else
|
else
|
||||||
b.heading = turtle.getHeadingInfo(stairDownDirections[b.direction]).heading
|
b.heading = getHeadingInfo(stairDownDirections[b.direction]).heading
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -767,7 +820,7 @@ function Schematic:determineBlockPlacement(y)
|
|||||||
if self:findIndexAt(b.x, b.z, b.y-1) then
|
if self:findIndexAt(b.x, b.z, b.y-1) then
|
||||||
-- there's a block below
|
-- there's a block below
|
||||||
b.direction = sd[1]
|
b.direction = sd[1]
|
||||||
b.heading = turtle.getHeadingInfo(b.direction).heading
|
b.heading = getHeadingInfo(b.direction).heading
|
||||||
else
|
else
|
||||||
local _,pb = self:findIndexAt(b.x + sd[3], b.z + sd[4], b.y)
|
local _,pb = self:findIndexAt(b.x + sd[3], b.z + sd[4], b.y)
|
||||||
if pb and pb.direction ~= sd[5] then
|
if pb and pb.direction ~= sd[5] then
|
||||||
@@ -775,7 +828,7 @@ function Schematic:determineBlockPlacement(y)
|
|||||||
d = sd[2] -- fall through to the blockDirections code below
|
d = sd[2] -- fall through to the blockDirections code below
|
||||||
b.direction = sd[2]
|
b.direction = sd[2]
|
||||||
else
|
else
|
||||||
b.heading = (turtle.getHeadingInfo(sd[1]).heading + 2) % 4
|
b.heading = (getHeadingInfo(sd[1]).heading + 2) % 4
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif flipDirections[d] then
|
elseif flipDirections[d] then
|
||||||
@@ -784,7 +837,7 @@ function Schematic:determineBlockPlacement(y)
|
|||||||
|
|
||||||
if blockDirections[d] then
|
if blockDirections[d] then
|
||||||
-- placing a block from the side
|
-- placing a block from the side
|
||||||
local hi = turtle.getHeadingInfo(blockDirections[d])
|
local hi = getHeadingInfo(blockDirections[d])
|
||||||
b.heading = hi.heading
|
b.heading = hi.heading
|
||||||
self:addPlacementChain(chains, {
|
self:addPlacementChain(chains, {
|
||||||
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
|
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
|
||||||
@@ -843,8 +896,6 @@ end
|
|||||||
-- set the order for block dependencies
|
-- set the order for block dependencies
|
||||||
function Schematic:setPlacementOrder(spinner, placementChains)
|
function Schematic:setPlacementOrder(spinner, placementChains)
|
||||||
|
|
||||||
local cursorX, cursorY = term.getCursorPos()
|
|
||||||
|
|
||||||
-- optimize for overlapping check
|
-- optimize for overlapping check
|
||||||
for _,chain in pairs(placementChains) do
|
for _,chain in pairs(placementChains) do
|
||||||
for index,_ in pairs(chain.keys) do
|
for index,_ in pairs(chain.keys) do
|
||||||
@@ -1040,8 +1091,6 @@ v.info = 'Unplaceable'
|
|||||||
end
|
end
|
||||||
|
|
||||||
term.clearLine()
|
term.clearLine()
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Schematic:optimizeRoute(spinner, y)
|
function Schematic:optimizeRoute(spinner, y)
|
||||||
@@ -1115,8 +1164,8 @@ function Schematic:optimizeRoute(spinner, y)
|
|||||||
return block
|
return block
|
||||||
end
|
end
|
||||||
|
|
||||||
local pt = Util.shallowCopy(self.cache[y - 1] or turtle.point)
|
local pt = Util.shallowCopy(self.cache[y - 1] or { x = -1, y = 0, z = -1, heading = 0 })
|
||||||
local t = {}
|
local t = { }
|
||||||
local ri = self.rowIndex[y]
|
local ri = self.rowIndex[y]
|
||||||
local blockCount = ri.e - ri.s + 1
|
local blockCount = ri.e - ri.s + 1
|
||||||
|
|
||||||
@@ -1146,7 +1195,6 @@ function Schematic:optimizeRoute(spinner, y)
|
|||||||
|
|
||||||
local maxDistance = self.width*self.length
|
local maxDistance = self.width*self.length
|
||||||
local plane, doors = extractPlane(y)
|
local plane, doors = extractPlane(y)
|
||||||
spinner:spin(percent)
|
|
||||||
pt.index = 0
|
pt.index = 0
|
||||||
for i = 1, #plane do
|
for i = 1, #plane do
|
||||||
local b = getNearestNeighbor(plane, pt, maxDistance)
|
local b = getNearestNeighbor(plane, pt, maxDistance)
|
||||||
1248
apis/builder/turtle.lua
Normal file
1248
apis/builder/turtle.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@ local function safeString(text)
|
|||||||
|
|
||||||
local newText = {}
|
local newText = {}
|
||||||
for i = 4, #text do
|
for i = 4, #text do
|
||||||
local val = text:byte(i)
|
val = text:byte(i)
|
||||||
newText[i - 3] = (val > 31 and val < 127) and val or 63
|
newText[i - 3] = (val > 31 and val < 127) and val or 63
|
||||||
end
|
end
|
||||||
return string.char(unpack(newText))
|
return string.char(unpack(newText))
|
||||||
@@ -86,13 +86,12 @@ function ChestAdapter:listItems(throttle)
|
|||||||
if not entry then
|
if not entry then
|
||||||
self.cache[key] = v
|
self.cache[key] = v
|
||||||
|
|
||||||
local ikey = { v.name, v.damage, v.nbtHash }
|
if not itemDB:get(v) then
|
||||||
if not itemDB:get(ikey) then
|
|
||||||
local t = { }
|
local t = { }
|
||||||
for _,k in pairs(keys) do
|
for _,k in pairs(keys) do
|
||||||
t[k] = v[k]
|
t[k] = v[k]
|
||||||
end
|
end
|
||||||
itemDB:add(ikey, t)
|
itemDB:add(t)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
entry.count = entry.count + v.count
|
entry.count = entry.count + v.count
|
||||||
@@ -110,11 +109,10 @@ function ChestAdapter:getItemInfo(item)
|
|||||||
return self.cache[key]
|
return self.cache[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:craft(id, dmg, qty)
|
function ChestAdapter:craft()
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:craftItems(items)
|
function ChestAdapter:craftItems()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:provide(item, qty, slot, direction)
|
function ChestAdapter:provide(item, qty, slot, direction)
|
||||||
@@ -144,7 +142,7 @@ end
|
|||||||
function ChestAdapter:insert(slot, qty)
|
function ChestAdapter:insert(slot, qty)
|
||||||
local s, m = pcall(function() self.pullItem(self.direction, slot, qty) end)
|
local s, m = pcall(function() self.pullItem(self.direction, slot, qty) end)
|
||||||
if not s and m then
|
if not s and m then
|
||||||
sleep(1)
|
os.sleep(1)
|
||||||
pcall(function() self.pullItem(self.direction, slot, qty) end)
|
pcall(function() self.pullItem(self.direction, slot, qty) end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,28 +5,23 @@ local Peripheral = require('peripheral')
|
|||||||
|
|
||||||
local ChestAdapter = class()
|
local ChestAdapter = class()
|
||||||
|
|
||||||
local keys = Util.transpose({
|
|
||||||
'damage',
|
|
||||||
'displayName',
|
|
||||||
'maxCount',
|
|
||||||
'maxDamage',
|
|
||||||
'name',
|
|
||||||
'nbtHash',
|
|
||||||
})
|
|
||||||
|
|
||||||
function ChestAdapter:init(args)
|
function ChestAdapter:init(args)
|
||||||
local defaults = {
|
local defaults = {
|
||||||
name = 'chest',
|
name = 'chest',
|
||||||
direction = 'up',
|
|
||||||
wrapSide = 'bottom',
|
|
||||||
}
|
}
|
||||||
Util.merge(self, defaults)
|
Util.merge(self, defaults)
|
||||||
Util.merge(self, args)
|
Util.merge(self, args)
|
||||||
|
|
||||||
local chest = Peripheral.getBySide(self.wrapSide)
|
local chest
|
||||||
if not chest then
|
if not self.side then
|
||||||
chest = Peripheral.getByMethod('list')
|
chest = Peripheral.getByMethod('list')
|
||||||
|
else
|
||||||
|
chest = Peripheral.getBySide(self.side)
|
||||||
|
if chest and not chest.list then
|
||||||
|
chest = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if chest then
|
if chest then
|
||||||
Util.merge(self, chest)
|
Util.merge(self, chest)
|
||||||
end
|
end
|
||||||
@@ -37,30 +32,19 @@ function ChestAdapter:isValid()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:getCachedItemDetails(item, k)
|
function ChestAdapter:getCachedItemDetails(item, k)
|
||||||
local key = { item.name, item.damage, item.nbtHash }
|
local cached = itemDB:get(item)
|
||||||
|
if cached then
|
||||||
local detail = itemDB:get(key)
|
return cached
|
||||||
if not detail then
|
|
||||||
pcall(function() detail = self.getItemMeta(k) end)
|
|
||||||
if not detail then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- NOT SUFFICIENT
|
|
||||||
if detail.name ~= item.name then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,k in ipairs(Util.keys(detail)) do
|
|
||||||
if not keys[k] then
|
|
||||||
detail[k] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
itemDB:add(key, detail)
|
|
||||||
end
|
end
|
||||||
if detail then
|
|
||||||
return Util.shallowCopy(detail)
|
local s, detail = pcall(self.getItemMeta, k)
|
||||||
|
if not s or not detail or detail.name ~= item.name then
|
||||||
|
-- debug({ s, detail })
|
||||||
|
-- error('Inventory has changed')
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return itemDB:add(detail)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:refresh(throttle)
|
function ChestAdapter:refresh(throttle)
|
||||||
@@ -69,33 +53,38 @@ end
|
|||||||
|
|
||||||
-- provide a consolidated list of items
|
-- provide a consolidated list of items
|
||||||
function ChestAdapter:listItems(throttle)
|
function ChestAdapter:listItems(throttle)
|
||||||
self.cache = { }
|
local cache = { }
|
||||||
local items = { }
|
local items = { }
|
||||||
|
|
||||||
throttle = throttle or Util.throttle()
|
throttle = throttle or Util.throttle()
|
||||||
|
|
||||||
for k,v in pairs(self.list()) do
|
for k,v in pairs(self.list()) do
|
||||||
local key = table.concat({ v.name, v.damage, v.nbtHash }, ':')
|
if v.count > 0 then
|
||||||
|
local key = table.concat({ v.name, v.damage, v.nbtHash }, ':')
|
||||||
|
|
||||||
local entry = self.cache[key]
|
local entry = cache[key]
|
||||||
if not entry then
|
if not entry then
|
||||||
entry = self:getCachedItemDetails(v, k)
|
entry = self:getCachedItemDetails(v, k)
|
||||||
if entry then
|
if not entry then
|
||||||
|
return -- Inventory has changed
|
||||||
|
end
|
||||||
|
entry = Util.shallowCopy(entry)
|
||||||
entry.count = 0
|
entry.count = 0
|
||||||
self.cache[key] = entry
|
cache[key] = entry
|
||||||
table.insert(items, entry)
|
table.insert(items, entry)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if entry then
|
if entry then
|
||||||
entry.count = entry.count + v.count
|
entry.count = entry.count + v.count
|
||||||
|
end
|
||||||
|
throttle()
|
||||||
end
|
end
|
||||||
throttle()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
itemDB:flush()
|
itemDB:flush()
|
||||||
|
|
||||||
return items
|
if not Util.empty(items) then
|
||||||
|
self.cache = cache
|
||||||
|
return items
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:getItemInfo(item)
|
function ChestAdapter:getItemInfo(item)
|
||||||
@@ -106,34 +95,68 @@ function ChestAdapter:getItemInfo(item)
|
|||||||
return self.cache[key]
|
return self.cache[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:craft(name, damage, qty)
|
function ChestAdapter:craft()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:craftItems(items)
|
function ChestAdapter:craftItems()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ChestAdapter:getPercentUsed()
|
||||||
|
if self.cache and self.getDrawerCount then
|
||||||
|
return math.floor(Util.size(self.cache) / self.getDrawerCount() * 100)
|
||||||
|
end
|
||||||
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:provide(item, qty, slot, direction)
|
function ChestAdapter:provide(item, qty, slot, direction)
|
||||||
local stacks = self.list()
|
local s, m = pcall(function()
|
||||||
for key,stack in pairs(stacks) do
|
local stacks = self.list()
|
||||||
if stack.name == item.name and stack.damage == item.damage then
|
for key,stack in Util.rpairs(stacks) do
|
||||||
local amount = math.min(qty, stack.count)
|
if stack.name == item.name and
|
||||||
if amount > 0 then
|
(not item.damage or stack.damage == item.damage) and
|
||||||
self.pushItems(direction or self.direction, key, amount, slot)
|
(not item.nbtHash or stack.nbtHash == item.nbtHash) then
|
||||||
end
|
local amount = math.min(qty, stack.count)
|
||||||
qty = qty - amount
|
if amount > 0 then
|
||||||
if qty <= 0 then
|
self.pushItems(direction or self.direction, key, amount, slot)
|
||||||
break
|
end
|
||||||
|
qty = qty - amount
|
||||||
|
if qty <= 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
return s, m
|
||||||
|
end
|
||||||
|
|
||||||
|
function ChestAdapter:eject(item, qty, direction)
|
||||||
|
local s, m = pcall(function()
|
||||||
|
local stacks = self.list()
|
||||||
|
local maxStack = itemDB:getMaxCount(item)
|
||||||
|
for key,stack in Util.rpairs(stacks) do
|
||||||
|
if stack.name == item.name and
|
||||||
|
(not item.damage or stack.damage == item.damage) and
|
||||||
|
(not item.nbtHash or stack.nbtHash == item.nbtHash) then
|
||||||
|
local amount = math.min(maxStack, math.min(qty, stack.count))
|
||||||
|
if amount > 0 then
|
||||||
|
self.drop(key, amount, direction)
|
||||||
|
end
|
||||||
|
qty = qty - amount
|
||||||
|
if qty <= 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return s, m
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:extract(slot, qty, toSlot)
|
function ChestAdapter:extract(slot, qty, toSlot)
|
||||||
self.pushItems(self.direction, slot, qty, toSlot)
|
self.pushItems(self.direction, slot, qty, toSlot)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ChestAdapter:insert(slot, qty)
|
function ChestAdapter:insert(slot, qty, toSlot)
|
||||||
self.pullItems(self.direction, slot, qty)
|
self.pullItems(self.direction, slot, qty, toSlot)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ChestAdapter
|
return ChestAdapter
|
||||||
|
|||||||
18
apis/controllerAdapter.lua
Normal file
18
apis/controllerAdapter.lua
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
local Adapter = { }
|
||||||
|
|
||||||
|
function Adapter.wrap(args)
|
||||||
|
local adapters = {
|
||||||
|
'refinedAdapter',
|
||||||
|
'meAdapter',
|
||||||
|
}
|
||||||
|
|
||||||
|
for _,adapterType in ipairs(adapters) do
|
||||||
|
local adapter = require(adapterType)(args)
|
||||||
|
|
||||||
|
if adapter:isValid() then
|
||||||
|
return adapter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Adapter
|
||||||
52
apis/inventoryAdapter.lua
Normal file
52
apis/inventoryAdapter.lua
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
local Util = require('util')
|
||||||
|
|
||||||
|
local Adapter = { }
|
||||||
|
|
||||||
|
function Adapter.wrap(args)
|
||||||
|
local adapters = {
|
||||||
|
--'refinedAdapter',
|
||||||
|
'chestAdapter18',
|
||||||
|
|
||||||
|
'meAdapter',
|
||||||
|
'chestAdapter',
|
||||||
|
}
|
||||||
|
|
||||||
|
if args and args.side and args.facing and not args.direction then
|
||||||
|
args = Util.shallowCopy(args)
|
||||||
|
local horz = { top = 'down', bottom = 'up' }
|
||||||
|
args.direction = horz[args.side]
|
||||||
|
|
||||||
|
if not args.direction then
|
||||||
|
local sides = {
|
||||||
|
front = 0,
|
||||||
|
back = 2,
|
||||||
|
right = 1,
|
||||||
|
left = 3,
|
||||||
|
}
|
||||||
|
-- pretty sure computer/turtle have sides reversed
|
||||||
|
local cards = {
|
||||||
|
east = 0,
|
||||||
|
south = 1,
|
||||||
|
west = 2,
|
||||||
|
north = 3,
|
||||||
|
}
|
||||||
|
local icards = {
|
||||||
|
[ 0 ] = 'west',
|
||||||
|
[ 1 ] = 'north',
|
||||||
|
[ 2 ] = 'east',
|
||||||
|
[ 3 ] = 'south',
|
||||||
|
}
|
||||||
|
args.direction = icards[(cards[args.facing] + sides[args.side]) % 4]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,adapterType in ipairs(adapters) do
|
||||||
|
local adapter = require(adapterType)(args)
|
||||||
|
|
||||||
|
if adapter:isValid() then
|
||||||
|
return adapter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Adapter
|
||||||
137
apis/itemDB.lua
137
apis/itemDB.lua
@@ -4,73 +4,165 @@ local Util = require('util')
|
|||||||
|
|
||||||
local itemDB = TableDB({ fileName = 'usr/config/items.db' })
|
local itemDB = TableDB({ fileName = 'usr/config/items.db' })
|
||||||
|
|
||||||
local function splitKey(key, item)
|
local function safeString(text)
|
||||||
|
local val = text:byte(1)
|
||||||
|
|
||||||
|
if val < 32 or val > 128 then
|
||||||
|
|
||||||
|
local newText = { }
|
||||||
|
local skip = 0
|
||||||
|
for i = 1, #text do
|
||||||
|
val = text:byte(i)
|
||||||
|
if val == 167 then
|
||||||
|
skip = 2
|
||||||
|
end
|
||||||
|
if skip > 0 then
|
||||||
|
skip = skip - 1
|
||||||
|
else
|
||||||
|
if val >= 32 and val <= 128 then
|
||||||
|
newText[#newText + 1] = val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return string.char(unpack(newText))
|
||||||
|
end
|
||||||
|
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
|
||||||
|
local function makeKey(item)
|
||||||
|
return table.concat({ item.name, item.damage or '*', item.nbtHash }, ':')
|
||||||
|
end
|
||||||
|
|
||||||
|
function itemDB:splitKey(key, item)
|
||||||
item = item or { }
|
item = item or { }
|
||||||
|
|
||||||
local t = Util.split(key, '(.-):')
|
local t = Util.split(key, '(.-):')
|
||||||
if #t[#t] > 8 then
|
if #t[#t] > 8 then
|
||||||
item.nbtHash = table.remove(t)
|
item.nbtHash = table.remove(t)
|
||||||
end
|
end
|
||||||
item.damage = tonumber(table.remove(t))
|
local damage = table.remove(t)
|
||||||
|
if damage ~= '*' then
|
||||||
|
item.damage = tonumber(damage)
|
||||||
|
end
|
||||||
item.name = table.concat(t, ':')
|
item.name = table.concat(t, ':')
|
||||||
|
|
||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
function itemDB:get(key)
|
function itemDB:get(key)
|
||||||
|
if type(key) == 'string' then
|
||||||
|
key = self:splitKey(key)
|
||||||
|
end
|
||||||
|
|
||||||
local item = TableDB.get(self, key)
|
local item = TableDB.get(self, makeKey(key))
|
||||||
|
|
||||||
if item then
|
if item then
|
||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
if key[2] ~= 0 then
|
-- try finding an item that has damage values
|
||||||
item = TableDB.get(self, { key[1], 0, key[3] })
|
if type(key.damage) == 'number' then
|
||||||
if item and item.maxDamage > 0 then
|
item = TableDB.get(self, makeKey({ name = key.name, nbtHash = key.nbtHash }))
|
||||||
|
if item and item.maxDamage then
|
||||||
item = Util.shallowCopy(item)
|
item = Util.shallowCopy(item)
|
||||||
item.damage = key[2]
|
item.damage = key.damage
|
||||||
item.displayName = string.format('%s (damage: %d)', item.displayName, item.damage)
|
if item.maxDamage > 0 and type(item.damage) == 'number' and item.damage > 0 then
|
||||||
|
item.displayName = string.format('%s (damage: %s)', item.displayName, item.damage)
|
||||||
|
end
|
||||||
|
return item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if key.nbtHash then
|
||||||
|
item = self:get({ name = key.name, damage = key.damage })
|
||||||
|
|
||||||
|
if item and item.ignoreNBT then
|
||||||
|
item = Util.shallowCopy(item)
|
||||||
|
item.nbtHash = key.nbtHash
|
||||||
|
item.damage = key.damage
|
||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function itemDB:add(key, item)
|
--[[
|
||||||
|
If the base item contains an NBT hash, then the NBT hash uniquely
|
||||||
|
identifies this item.
|
||||||
|
]]--
|
||||||
|
function itemDB:add(baseItem)
|
||||||
|
local nItem = {
|
||||||
|
name = baseItem.name,
|
||||||
|
damage = baseItem.damage,
|
||||||
|
nbtHash = baseItem.nbtHash,
|
||||||
|
}
|
||||||
|
-- if detail.maxDamage > 0 then
|
||||||
|
-- nItem.damage = '*'
|
||||||
|
-- end
|
||||||
|
|
||||||
if item.maxDamage > 0 then
|
nItem.displayName = safeString(baseItem.displayName)
|
||||||
key = { key[1], 0, key[3] }
|
nItem.maxCount = baseItem.maxCount
|
||||||
|
nItem.maxDamage = baseItem.maxDamage
|
||||||
|
|
||||||
|
for k,item in pairs(self.data) do
|
||||||
|
if nItem.name == item.name and
|
||||||
|
nItem.displayName == item.displayName then
|
||||||
|
|
||||||
|
if nItem.nbtHash ~= item.nbtHash and nItem.damage ~= item.damage then
|
||||||
|
nItem.damage = '*'
|
||||||
|
nItem.nbtHash = nil
|
||||||
|
nItem.ignoreNBT = true
|
||||||
|
self.data[k] = nil
|
||||||
|
break
|
||||||
|
elseif nItem.damage ~= item.damage then
|
||||||
|
nItem.damage = '*'
|
||||||
|
self.data[k] = nil
|
||||||
|
break
|
||||||
|
elseif nItem.nbtHash ~= item.nbtHash then
|
||||||
|
nItem.nbtHash = nil
|
||||||
|
nItem.ignoreNBT = true
|
||||||
|
self.data[k] = nil
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
TableDB.add(self, key, item)
|
|
||||||
end
|
|
||||||
|
|
||||||
function itemDB:makeKey(item)
|
TableDB.add(self, makeKey(nItem), nItem)
|
||||||
return { item.name, item.damage, item.nbtHash }
|
nItem = Util.shallowCopy(nItem)
|
||||||
|
nItem.damage = baseItem.damage
|
||||||
|
nItem.nbtHash = baseItem.nbtHash
|
||||||
|
|
||||||
|
return nItem
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Accepts: "minecraft:stick:0" or { name = 'minecraft:stick', damage = 0 }
|
-- Accepts: "minecraft:stick:0" or { name = 'minecraft:stick', damage = 0 }
|
||||||
function itemDB:getName(item)
|
function itemDB:getName(item)
|
||||||
|
|
||||||
if type(item) == 'string' then
|
if type(item) == 'string' then
|
||||||
item = splitKey(item)
|
item = self:splitKey(item)
|
||||||
end
|
end
|
||||||
|
|
||||||
local detail = self:get(self:makeKey(item))
|
local detail = self:get(item)
|
||||||
if detail then
|
if detail then
|
||||||
return detail.displayName
|
return detail.displayName
|
||||||
end
|
end
|
||||||
|
|
||||||
-- fallback to nameDB
|
-- fallback to nameDB
|
||||||
return nameDB:getName(item.name .. ':' .. item.damage)
|
return nameDB:getName(item.name .. ':' .. (item.damage or '*'))
|
||||||
|
end
|
||||||
|
|
||||||
|
function itemDB:getMaxCount(item)
|
||||||
|
local detail = self:get(item)
|
||||||
|
if detail then
|
||||||
|
return detail.maxCount
|
||||||
|
end
|
||||||
|
|
||||||
|
return 64
|
||||||
end
|
end
|
||||||
|
|
||||||
function itemDB:load()
|
function itemDB:load()
|
||||||
|
|
||||||
TableDB.load(self)
|
TableDB.load(self)
|
||||||
|
|
||||||
for key,item in pairs(self.data) do
|
for key,item in pairs(self.data) do
|
||||||
splitKey(key, item)
|
self:splitKey(key, item)
|
||||||
item.maxDamage = item.maxDamage or 0
|
item.maxDamage = item.maxDamage or 0
|
||||||
item.maxCount = item.maxCount or 64
|
item.maxCount = item.maxCount or 64
|
||||||
end
|
end
|
||||||
@@ -85,6 +177,7 @@ function itemDB:flush()
|
|||||||
v.name = nil
|
v.name = nil
|
||||||
v.damage = nil
|
v.damage = nil
|
||||||
v.nbtHash = nil
|
v.nbtHash = nil
|
||||||
|
v.count = nil -- wipe out previously saved counts - temporary
|
||||||
if v.maxDamage == 0 then
|
if v.maxDamage == 0 then
|
||||||
v.maxDamage = nil
|
v.maxDamage = nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ local itemDB = require('itemDB')
|
|||||||
local Peripheral = require('peripheral')
|
local Peripheral = require('peripheral')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
local MEAdapter = class()
|
local os = _G.os
|
||||||
|
local peripheral = _G.peripheral
|
||||||
|
|
||||||
local convertNames = {
|
local convertNames = {
|
||||||
name = 'id',
|
name = 'id',
|
||||||
@@ -31,7 +32,7 @@ local function safeString(text)
|
|||||||
|
|
||||||
local newText = {}
|
local newText = {}
|
||||||
for i = 4, #text do
|
for i = 4, #text do
|
||||||
local val = text:byte(i)
|
val = text:byte(i)
|
||||||
newText[i - 3] = (val > 31 and val < 127) and val or 63
|
newText[i - 3] = (val > 31 and val < 127) and val or 63
|
||||||
end
|
end
|
||||||
return string.char(unpack(newText))
|
return string.char(unpack(newText))
|
||||||
@@ -48,29 +49,31 @@ local function convertItem(item)
|
|||||||
item.displayName = safeString(item.displayName)
|
item.displayName = safeString(item.displayName)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local MEAdapter = class()
|
||||||
|
|
||||||
function MEAdapter:init(args)
|
function MEAdapter:init(args)
|
||||||
local defaults = {
|
local defaults = {
|
||||||
items = { },
|
items = { },
|
||||||
name = 'ME',
|
name = 'ME',
|
||||||
jobList = { },
|
jobList = { },
|
||||||
direction = 'up',
|
|
||||||
wrapSide = 'bottom',
|
|
||||||
auto = false,
|
|
||||||
}
|
}
|
||||||
Util.merge(self, defaults)
|
Util.merge(self, defaults)
|
||||||
Util.merge(self, args)
|
Util.merge(self, args)
|
||||||
|
|
||||||
if self.auto then
|
local chest
|
||||||
local mep = Peripheral.getByMethod('getAvailableItems')
|
|
||||||
if mep then
|
if not self.side then
|
||||||
Util.merge(self, mep)
|
chest = Peripheral.getByMethod('getAvailableItems')
|
||||||
end
|
|
||||||
else
|
else
|
||||||
local mep = peripheral.wrap(self.wrapSide)
|
chest = Peripheral.getBySide(self.side)
|
||||||
if mep then
|
if chest and not chest.getAvailableItems then
|
||||||
Util.merge(self, mep)
|
chest = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if chest then
|
||||||
|
Util.merge(self, chest)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function MEAdapter:isValid()
|
function MEAdapter:isValid()
|
||||||
@@ -84,13 +87,8 @@ function MEAdapter:refresh()
|
|||||||
Util.merge(v, v.item)
|
Util.merge(v, v.item)
|
||||||
convertItem(v)
|
convertItem(v)
|
||||||
|
|
||||||
local key = { v.name, v.damage, v.nbtHash }
|
if not itemDB:get(v) then
|
||||||
if not itemDB:get(key) then
|
itemDB:add(v, v)
|
||||||
local t = { }
|
|
||||||
for _,k in pairs(keys) do
|
|
||||||
t[k] = v[k]
|
|
||||||
end
|
|
||||||
itemDB:add(key, t)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
itemDB:flush()
|
itemDB:flush()
|
||||||
@@ -104,7 +102,7 @@ function MEAdapter:listItems()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MEAdapter:getItemInfo(item)
|
function MEAdapter:getItemInfo(item)
|
||||||
for key,i in pairs(self.items) do
|
for _,i in pairs(self.items) do
|
||||||
if item.name == i.name and item.damage == i.damage and item.nbtHash == i.nbtHash then
|
if item.name == i.name and item.damage == i.damage and item.nbtHash == i.nbtHash then
|
||||||
return i
|
return i
|
||||||
end
|
end
|
||||||
@@ -133,7 +131,7 @@ function MEAdapter:craft(item, count)
|
|||||||
|
|
||||||
self:refresh()
|
self:refresh()
|
||||||
|
|
||||||
local item = self:getItemInfo(item)
|
item = self:getItemInfo(item)
|
||||||
if item and item.is_craftable then
|
if item and item.is_craftable then
|
||||||
|
|
||||||
local cpus = self.getCraftingCPUs() or { }
|
local cpus = self.getCraftingCPUs() or { }
|
||||||
@@ -220,7 +218,7 @@ function MEAdapter:provide(item, count, slot, direction)
|
|||||||
return pcall(function()
|
return pcall(function()
|
||||||
while count > 0 do
|
while count > 0 do
|
||||||
local qty = math.min(count, 64)
|
local qty = math.min(count, 64)
|
||||||
local s, m = self.exportItem({
|
local s = self.exportItem({
|
||||||
id = item.name,
|
id = item.name,
|
||||||
dmg = item.damage
|
dmg = item.damage
|
||||||
}, direction or self.direction, qty, slot)
|
}, direction or self.direction, qty, slot)
|
||||||
@@ -236,14 +234,10 @@ end
|
|||||||
function MEAdapter:insert(slot, count)
|
function MEAdapter:insert(slot, count)
|
||||||
local s, m = pcall(function() self.pullItem(self.direction, slot, count) end)
|
local s, m = pcall(function() self.pullItem(self.direction, slot, count) end)
|
||||||
if not s and m then
|
if not s and m then
|
||||||
print('MEAdapter:pullItem')
|
os.sleep(1)
|
||||||
print(m)
|
|
||||||
sleep(1)
|
|
||||||
s, m = pcall(function() self.pullItem(self.direction, slot, count) end)
|
s, m = pcall(function() self.pullItem(self.direction, slot, count) end)
|
||||||
if not s and m then
|
if not s and m then
|
||||||
print('MEAdapter:pullItem')
|
error(m)
|
||||||
print(m)
|
|
||||||
read()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ function nameDB:load()
|
|||||||
end
|
end
|
||||||
|
|
||||||
for strId, block in pairs(blocks) do
|
for strId, block in pairs(blocks) do
|
||||||
local strId = 'minecraft:' .. strId
|
strId = 'minecraft:' .. strId
|
||||||
if type(block.name) == 'string' then
|
if type(block.name) == 'string' then
|
||||||
self.data[strId .. ':0'] = block.name
|
self.data[strId .. ':0'] = block.name
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -18,11 +18,22 @@ function RefinedAdapter:init(args)
|
|||||||
local defaults = {
|
local defaults = {
|
||||||
items = { },
|
items = { },
|
||||||
name = 'refinedStorage',
|
name = 'refinedStorage',
|
||||||
|
direction = 'up',
|
||||||
|
wrapSide = 'bottom',
|
||||||
}
|
}
|
||||||
Util.merge(self, defaults)
|
Util.merge(self, defaults)
|
||||||
Util.merge(self, args)
|
Util.merge(self, args)
|
||||||
|
|
||||||
local controller = Peripheral.getByType('refinedstorage:controller')
|
local controller
|
||||||
|
if self.autoDetect then
|
||||||
|
controller = Peripheral.getByType('refinedstorage:controller')
|
||||||
|
else
|
||||||
|
controller = Peripheral.getBySide(self.wrapSide)
|
||||||
|
if controller and not controller.listAvailableItems then
|
||||||
|
controller = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if controller then
|
if controller then
|
||||||
Util.merge(self, controller)
|
Util.merge(self, controller)
|
||||||
end
|
end
|
||||||
@@ -37,9 +48,7 @@ function RefinedAdapter:isOnline()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function RefinedAdapter:getCachedItemDetails(item)
|
function RefinedAdapter:getCachedItemDetails(item)
|
||||||
local key = { item.name, item.damage, item.nbtHash }
|
local detail = itemDB:get(item)
|
||||||
|
|
||||||
local detail = itemDB:get(key)
|
|
||||||
if not detail then
|
if not detail then
|
||||||
detail = self.findItem(item)
|
detail = self.findItem(item)
|
||||||
if detail then
|
if detail then
|
||||||
@@ -56,7 +65,7 @@ function RefinedAdapter:getCachedItemDetails(item)
|
|||||||
end
|
end
|
||||||
|
|
||||||
detail = t
|
detail = t
|
||||||
itemDB:add(key, detail)
|
itemDB:add(detail)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if detail then
|
if detail then
|
||||||
@@ -91,10 +100,7 @@ function RefinedAdapter:listItems()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function RefinedAdapter:getItemInfo(fingerprint)
|
function RefinedAdapter:getItemInfo(fingerprint)
|
||||||
|
local item = itemDB:get(fingerprint)
|
||||||
local key = { fingerprint.name, fingerprint.damage, fingerprint.nbtHash }
|
|
||||||
|
|
||||||
local item = itemDB:get(key)
|
|
||||||
if not item then
|
if not item then
|
||||||
return self:getCachedItemDetails(fingerprint)
|
return self:getCachedItemDetails(fingerprint)
|
||||||
end
|
end
|
||||||
@@ -125,18 +131,18 @@ function RefinedAdapter:craft(item, qty)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function RefinedAdapter:craftItems(items)
|
function RefinedAdapter:craftItems()
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function RefinedAdapter:provide(item, qty, slot)
|
function RefinedAdapter:provide()
|
||||||
end
|
end
|
||||||
|
|
||||||
function RefinedAdapter:extract(slot, qty)
|
function RefinedAdapter:extract()
|
||||||
-- self.pushItems(self.direction, slot, qty)
|
-- self.pushItems(self.direction, slot, qty)
|
||||||
end
|
end
|
||||||
|
|
||||||
function RefinedAdapter:insert(slot, qty)
|
function RefinedAdapter:insert()
|
||||||
-- self.pullItems(self.direction, slot, qty)
|
-- self.pullItems(self.direction, slot, qty)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
local itemDB = require('itemDB')
|
local itemDB = require('itemDB')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
|
local RECIPES_DIR = 'usr/etc/recipes'
|
||||||
|
|
||||||
local Craft = { }
|
local Craft = { }
|
||||||
|
|
||||||
local function clearGrid(inventoryAdapter)
|
local function clearGrid(inventoryAdapter)
|
||||||
@@ -9,6 +14,7 @@ local function clearGrid(inventoryAdapter)
|
|||||||
if count > 0 then
|
if count > 0 then
|
||||||
inventoryAdapter:insert(i, count)
|
inventoryAdapter:insert(i, count)
|
||||||
if turtle.getItemCount(i) ~= 0 then
|
if turtle.getItemCount(i) ~= 0 then
|
||||||
|
-- inventory is possibly full
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -27,27 +33,44 @@ local function splitKey(key)
|
|||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getItemCount(items, key)
|
function Craft.getItemCount(items, item)
|
||||||
local item = splitKey(key)
|
if type(item) == 'string' then
|
||||||
|
item = splitKey(item)
|
||||||
|
end
|
||||||
|
|
||||||
|
local count = 0
|
||||||
for _,v in pairs(items) do
|
for _,v in pairs(items) do
|
||||||
if v.name == item.name and
|
if v.name == item.name and
|
||||||
v.damage == item.damage and
|
(not item.damage or v.damage == item.damage) and
|
||||||
v.nbtHash == item.nbtHash then
|
v.nbtHash == item.nbtHash then
|
||||||
return v.count
|
if item.damage then
|
||||||
|
return v.count
|
||||||
|
end
|
||||||
|
count = count + v.count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return 0
|
return count
|
||||||
end
|
end
|
||||||
|
|
||||||
local function turtleCraft(recipe, qty, inventoryAdapter)
|
local function turtleCraft(recipe, qty, inventoryAdapter)
|
||||||
|
if not clearGrid(inventoryAdapter) then
|
||||||
clearGrid(inventoryAdapter)
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
for k,v in pairs(recipe.ingredients) do
|
for k,v in pairs(recipe.ingredients) do
|
||||||
local item = splitKey(v)
|
local item = splitKey(v)
|
||||||
inventoryAdapter:provide(item, qty, k)
|
local provideQty = qty
|
||||||
|
--[[
|
||||||
|
Turtles can only craft 1 item at a time when using a tool.
|
||||||
|
|
||||||
|
if recipe.craftingTools and recipe.craftingTools[k] then
|
||||||
|
provideQty = 1
|
||||||
|
end
|
||||||
|
]]--
|
||||||
|
inventoryAdapter:provide(item, provideQty, k)
|
||||||
if turtle.getItemCount(k) == 0 then -- ~= qty then
|
if turtle.getItemCount(k) == 0 then -- ~= qty then
|
||||||
-- FIX: ingredients cannot be stacked
|
-- FIX: ingredients cannot be stacked
|
||||||
|
--debug('failed ' .. v .. ' - ' .. provideQty)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -55,65 +78,166 @@ local function turtleCraft(recipe, qty, inventoryAdapter)
|
|||||||
return turtle.craft()
|
return turtle.craft()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Craft.loadRecipes()
|
||||||
|
Craft.recipes = Util.readTable(fs.combine(RECIPES_DIR, 'minecraft.db')) or { }
|
||||||
|
|
||||||
|
local files = fs.list('usr/etc/recipes')
|
||||||
|
table.sort(files)
|
||||||
|
Util.removeByValue(files, 'minecraft.db')
|
||||||
|
|
||||||
|
for _,file in ipairs(files) do
|
||||||
|
local recipes = Util.readTable(fs.combine(RECIPES_DIR, file))
|
||||||
|
Util.merge(Craft.recipes, recipes)
|
||||||
|
end
|
||||||
|
|
||||||
|
local recipes = Util.readTable('usr/config/recipes.db') or { }
|
||||||
|
Util.merge(Craft.recipes, recipes)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Craft.sumIngredients(recipe)
|
||||||
|
-- produces { ['minecraft:planks:0'] = 8 }
|
||||||
|
local t = { }
|
||||||
|
for _,item in pairs(recipe.ingredients) do
|
||||||
|
t[item] = (t[item] or 0) + 1
|
||||||
|
end
|
||||||
|
-- need a check for crafting tool
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
function Craft.craftRecipe(recipe, count, inventoryAdapter)
|
function Craft.craftRecipe(recipe, count, inventoryAdapter)
|
||||||
|
if type(recipe) == 'string' then
|
||||||
|
recipe = Craft.recipes[recipe]
|
||||||
|
if not recipe then
|
||||||
|
return 0, 'No recipe'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local items = inventoryAdapter:listItems()
|
local items = inventoryAdapter:listItems()
|
||||||
|
if not items then
|
||||||
local function sumItems(items)
|
return 0, 'Inventory changed'
|
||||||
-- produces { ['minecraft:planks:0'] = 8 }
|
|
||||||
local t = {}
|
|
||||||
for _,item in pairs(items) do
|
|
||||||
t[item] = (t[item] or 0) + 1
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
end
|
||||||
|
|
||||||
count = math.ceil(count / recipe.count)
|
count = math.ceil(count / recipe.count)
|
||||||
|
|
||||||
local maxCount = recipe.maxCount or math.floor(64 / recipe.count)
|
local maxCount = recipe.maxCount or math.floor(64 / recipe.count)
|
||||||
local summedItems = sumItems(recipe.ingredients)
|
|
||||||
|
|
||||||
for key,icount in pairs(summedItems) do
|
for key,icount in pairs(Craft.sumIngredients(recipe)) do
|
||||||
local itemCount = getItemCount(items, key)
|
local itemCount = Craft.getItemCount(items, key)
|
||||||
if itemCount < icount * count then
|
if itemCount < icount * count then
|
||||||
local irecipe = Craft.recipes[key]
|
local irecipe = Craft.recipes[key]
|
||||||
if irecipe then
|
if irecipe then
|
||||||
--Util.print('Crafting %d %s', icount * count - itemCount, key)
|
local iqty = icount * count - itemCount
|
||||||
if not Craft.craftRecipe(irecipe,
|
local crafted = Craft.craftRecipe(irecipe, iqty, inventoryAdapter)
|
||||||
icount * count - itemCount,
|
if crafted ~= iqty then
|
||||||
inventoryAdapter) then
|
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
return
|
return 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local crafted = 0
|
||||||
repeat
|
repeat
|
||||||
if not turtleCraft(recipe, math.min(count, maxCount), inventoryAdapter) then
|
if not turtleCraft(recipe, math.min(count, maxCount), inventoryAdapter) then
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
return false
|
break
|
||||||
end
|
end
|
||||||
|
crafted = crafted + math.min(count, maxCount)
|
||||||
count = count - maxCount
|
count = count - maxCount
|
||||||
until count <= 0
|
until count <= 0
|
||||||
|
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
return true
|
return crafted * recipe.count
|
||||||
|
end
|
||||||
|
|
||||||
|
local function makeRecipeKey(item)
|
||||||
|
if type(item) == 'string' then
|
||||||
|
item = splitKey(item)
|
||||||
|
end
|
||||||
|
return table.concat({ item.name, item.damage or 0, item.nbtHash }, ':')
|
||||||
|
end
|
||||||
|
|
||||||
|
function Craft.findRecipe(item)
|
||||||
|
return Craft.recipes[makeRecipeKey(item)]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- determine the full list of ingredients needed to craft
|
||||||
|
-- a quantity of a recipe.
|
||||||
|
function Craft.getResourceList(recipe, items, inCount)
|
||||||
|
local summed = { }
|
||||||
|
|
||||||
|
local function sumItems(key, count)
|
||||||
|
local item = itemDB:splitKey(key)
|
||||||
|
local summedItem = summed[key]
|
||||||
|
if not summedItem then
|
||||||
|
summedItem = Util.shallowCopy(item)
|
||||||
|
summedItem.recipe = Craft.findRecipe(key)
|
||||||
|
summedItem.count = Craft.getItemCount(items, item)
|
||||||
|
summedItem.displayName = itemDB:getName(item)
|
||||||
|
summedItem.total = 0
|
||||||
|
summedItem.need = 0
|
||||||
|
summedItem.used = 0
|
||||||
|
summed[key] = summedItem
|
||||||
|
end
|
||||||
|
local total = count
|
||||||
|
local used = math.min(summedItem.count, total)
|
||||||
|
local need = total - used
|
||||||
|
|
||||||
|
if summedItem.recipe and summedItem.recipe.craftingTools and summedItem.recipe.craftingTools[key] then
|
||||||
|
summedItem.total = 1
|
||||||
|
if summedItem.count > 0 then
|
||||||
|
summedItem.used = 1
|
||||||
|
summedItem.need = 0
|
||||||
|
need = 0
|
||||||
|
else
|
||||||
|
if not summedItem.recipe then
|
||||||
|
summedItem.need = 1
|
||||||
|
need = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
summedItem.total = summedItem.total + total
|
||||||
|
summedItem.count = summedItem.count - used
|
||||||
|
summedItem.used = summedItem.used + used
|
||||||
|
if not summedItem.recipe then
|
||||||
|
summedItem.need = summedItem.need + need
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if need > 0 and summedItem.recipe then
|
||||||
|
need = math.ceil(need / summedItem.recipe.count)
|
||||||
|
for ikey,iqty in pairs(Craft.sumIngredients(summedItem.recipe)) do
|
||||||
|
sumItems(ikey, math.ceil(need * iqty))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
inCount = math.ceil(inCount / recipe.count)
|
||||||
|
for ikey,iqty in pairs(Craft.sumIngredients(recipe)) do
|
||||||
|
sumItems(ikey, math.ceil(inCount * iqty))
|
||||||
|
end
|
||||||
|
|
||||||
|
return summed
|
||||||
|
end
|
||||||
|
|
||||||
|
function Craft.getResourceList4(inRecipe, items, count)
|
||||||
|
local summed = Craft.getResourceList(inRecipe, items, count)
|
||||||
|
-- filter down to just raw materials
|
||||||
|
return Util.filter(summed, function(a) return a.used > 0 or a.need > 0 end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- given a certain quantity, return how many of those can be crafted
|
-- given a certain quantity, return how many of those can be crafted
|
||||||
function Craft.getCraftableAmount(recipe, count, items, missing)
|
function Craft.getCraftableAmount(recipe, count, items, missing)
|
||||||
|
local function sumItems(recipe, summedItems, count)
|
||||||
local function sumItems(recipe, items, summedItems, count)
|
|
||||||
|
|
||||||
local canCraft = 0
|
local canCraft = 0
|
||||||
|
|
||||||
for i = 1, count do
|
for _ = 1, count do
|
||||||
for _,item in pairs(recipe.ingredients) do
|
for _,item in pairs(recipe.ingredients) do
|
||||||
local summedItem = summedItems[item] or getItemCount(items, item)
|
local summedItem = summedItems[item] or Craft.getItemCount(items, item)
|
||||||
|
|
||||||
local irecipe = Craft.recipes[item]
|
local irecipe = Craft.recipes[item]
|
||||||
if irecipe and summedItem <= 0 then
|
if irecipe and summedItem <= 0 then
|
||||||
summedItem = summedItem + sumItems(irecipe, items, summedItems, 1)
|
summedItem = summedItem + sumItems(irecipe, summedItems, 1)
|
||||||
end
|
end
|
||||||
if summedItem <= 0 then
|
if summedItem <= 0 then
|
||||||
if missing then
|
if missing then
|
||||||
@@ -121,7 +245,9 @@ function Craft.getCraftableAmount(recipe, count, items, missing)
|
|||||||
end
|
end
|
||||||
return canCraft
|
return canCraft
|
||||||
end
|
end
|
||||||
summedItems[item] = summedItem - 1
|
if not recipe.craftingTools or not recipe.craftingTools[item] then
|
||||||
|
summedItems[item] = summedItem - 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
canCraft = canCraft + recipe.count
|
canCraft = canCraft + recipe.count
|
||||||
end
|
end
|
||||||
@@ -129,7 +255,7 @@ function Craft.getCraftableAmount(recipe, count, items, missing)
|
|||||||
return canCraft
|
return canCraft
|
||||||
end
|
end
|
||||||
|
|
||||||
return sumItems(recipe, items, { }, math.ceil(count / recipe.count), missing)
|
return sumItems(recipe, { }, math.ceil(count / recipe.count))
|
||||||
end
|
end
|
||||||
|
|
||||||
function Craft.canCraft(item, count, items)
|
function Craft.canCraft(item, count, items)
|
||||||
@@ -148,13 +274,15 @@ function Craft.getCraftableAmountTest()
|
|||||||
{ name = 'minecraft:planks', damage = 0, count = 5 },
|
{ name = 'minecraft:planks', damage = 0, count = 5 },
|
||||||
{ name = 'minecraft:log', damage = 0, count = 2 },
|
{ name = 'minecraft:log', damage = 0, count = 2 },
|
||||||
}
|
}
|
||||||
results[1] = { item = 'chest', expected = 1, got = Craft.getCraftableAmount(Craft.recipes['minecraft:chest:0'], 2, items) }
|
results[1] = { item = 'chest', expected = 1,
|
||||||
|
got = Craft.getCraftableAmount(Craft.recipes['minecraft:chest:0'], 2, items) }
|
||||||
|
|
||||||
items = {
|
items = {
|
||||||
{ name = 'minecraft:log', damage = 0, count = 1 },
|
{ name = 'minecraft:log', damage = 0, count = 1 },
|
||||||
{ name = 'minecraft:coal', damage = 1, count = 1 },
|
{ name = 'minecraft:coal', damage = 1, count = 1 },
|
||||||
}
|
}
|
||||||
results[2] = { item = 'torch', expected = 4, got = Craft.getCraftableAmount(Craft.recipes['minecraft:torch:0'], 4, items) }
|
results[2] = { item = 'torch', expected = 4,
|
||||||
|
got = Craft.getCraftableAmount(Craft.recipes['minecraft:torch:0'], 4, items) }
|
||||||
|
|
||||||
return results
|
return results
|
||||||
end
|
end
|
||||||
@@ -166,4 +294,6 @@ function Craft.craftRecipeTest(name, count)
|
|||||||
return { Craft.craftRecipe(Craft.recipes[name], count, chestAdapter) }
|
return { Craft.craftRecipe(Craft.recipes[name], count, chestAdapter) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Craft.loadRecipes()
|
||||||
|
|
||||||
return Craft
|
return Craft
|
||||||
|
|||||||
67
apis/turtle/crafting.lua
Normal file
67
apis/turtle/crafting.lua
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
local Adapter = require('inventoryAdapter')
|
||||||
|
local Craft = require('turtle.craft')
|
||||||
|
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
|
local CRAFTING_TABLE = 'minecraft:crafting_table'
|
||||||
|
|
||||||
|
local function clearGrid(inventory)
|
||||||
|
print('clearing')
|
||||||
|
for i = 1, 16 do
|
||||||
|
local count = turtle.getItemCount(i)
|
||||||
|
if count > 0 then
|
||||||
|
inventory:insert(i, count)
|
||||||
|
if turtle.getItemCount(i) ~= 0 then
|
||||||
|
print('failed to insert')
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function turtle.craftItem(item, count, inventoryInfo)
|
||||||
|
local success, msg
|
||||||
|
|
||||||
|
local inventory = Adapter.wrap(inventoryInfo)
|
||||||
|
if not inventory then
|
||||||
|
return false, 'Invalid inventory'
|
||||||
|
end
|
||||||
|
|
||||||
|
local equipped, side
|
||||||
|
if not turtle.isEquipped('workbench') then
|
||||||
|
local modemSide = turtle.isEquipped('modem') or 'right'
|
||||||
|
local osides = { left = 'right', right = 'left' }
|
||||||
|
side = osides[modemSide]
|
||||||
|
if not turtle.select(CRAFTING_TABLE) then
|
||||||
|
clearGrid(inventory)
|
||||||
|
if not turtle.selectOpenSlot() then
|
||||||
|
return false, 'Inventory is full'
|
||||||
|
end
|
||||||
|
if not inventory:provide({ name = CRAFTING_TABLE, damage = 0 }, 1) then
|
||||||
|
return false, 'Missing crafting table'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local slot = turtle.select(CRAFTING_TABLE)
|
||||||
|
turtle.equip(side, CRAFTING_TABLE)
|
||||||
|
equipped = turtle.getItemDetail(slot.index)
|
||||||
|
end
|
||||||
|
|
||||||
|
clearGrid(inventory)
|
||||||
|
success, msg = Craft.craftRecipe(item, count or 1, inventory)
|
||||||
|
|
||||||
|
if equipped then
|
||||||
|
turtle.selectOpenSlot()
|
||||||
|
inventory:provide({ name = equipped.name, damage = equipped.damage }, 1)
|
||||||
|
turtle.equip(side, equipped.name .. ':' .. equipped.damage)
|
||||||
|
end
|
||||||
|
|
||||||
|
return success, msg
|
||||||
|
end
|
||||||
|
|
||||||
|
function turtle.canCraft(item, count, items)
|
||||||
|
return Craft.canCraft(item, count, items)
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
42
apis/turtle/home.lua
Normal file
42
apis/turtle/home.lua
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
local Config = require('config')
|
||||||
|
local GPS = require('gps')
|
||||||
|
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
|
local Home = { }
|
||||||
|
|
||||||
|
function Home.go()
|
||||||
|
local config = { }
|
||||||
|
Config.load('gps', config)
|
||||||
|
|
||||||
|
if config.home then
|
||||||
|
if turtle.enableGPS() then
|
||||||
|
return turtle.pathfind(config.home)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Home.set()
|
||||||
|
local config = { }
|
||||||
|
Config.load('gps', config)
|
||||||
|
|
||||||
|
local pt = GPS.getPoint()
|
||||||
|
if pt then
|
||||||
|
local originalHeading = turtle.point.heading
|
||||||
|
local heading = GPS.getHeading()
|
||||||
|
if heading then
|
||||||
|
local turns = (turtle.point.heading - originalHeading) % 4
|
||||||
|
pt.heading = (heading - turns) % 4
|
||||||
|
config.home = pt
|
||||||
|
Config.update('gps', config)
|
||||||
|
|
||||||
|
pt = GPS.getPoint()
|
||||||
|
pt.heading = heading
|
||||||
|
turtle.setPoint(pt, true)
|
||||||
|
turtle._goto(config.home)
|
||||||
|
return config.home
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Home
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
local Point = require('point')
|
local Point = require('point')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
local checkedNodes = { }
|
local checkedNodes = { }
|
||||||
local nodes = { }
|
local nodes = { }
|
||||||
local box = { }
|
local box = { }
|
||||||
@@ -11,7 +13,6 @@ local function toKey(pt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function addNode(node)
|
local function addNode(node)
|
||||||
|
|
||||||
for i = 0, 5 do
|
for i = 0, 5 do
|
||||||
local hi = turtle.getHeadingInfo(i)
|
local hi = turtle.getHeadingInfo(i)
|
||||||
local testNode = { x = node.x + hi.xd, y = node.y + hi.yd, z = node.z + hi.zd }
|
local testNode = { x = node.x + hi.xd, y = node.y + hi.yd, z = node.z + hi.zd }
|
||||||
@@ -26,7 +27,6 @@ local function addNode(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function dig(action)
|
local function dig(action)
|
||||||
|
|
||||||
local directions = {
|
local directions = {
|
||||||
top = 'up',
|
top = 'up',
|
||||||
bottom = 'down',
|
bottom = 'down',
|
||||||
@@ -75,7 +75,7 @@ end
|
|||||||
-- find the closest block
|
-- find the closest block
|
||||||
-- * favor same plane
|
-- * favor same plane
|
||||||
-- * going backwards only if the dest is above or below
|
-- * going backwards only if the dest is above or below
|
||||||
function closestPoint(reference, pts)
|
local function closestPoint(reference, pts)
|
||||||
local lpt, lm -- lowest
|
local lpt, lm -- lowest
|
||||||
for _,pt in pairs(pts) do
|
for _,pt in pairs(pts) do
|
||||||
local m = Point.turtleDistance(reference, pt)
|
local m = Point.turtleDistance(reference, pt)
|
||||||
@@ -113,8 +113,7 @@ local function getAdjacentPoint(pt)
|
|||||||
return closestPoint(turtle.getPoint(), t)
|
return closestPoint(turtle.getPoint(), t)
|
||||||
end
|
end
|
||||||
|
|
||||||
return function(startPt, endPt, firstPt, verbose)
|
function turtle.level(startPt, endPt, firstPt, verbose)
|
||||||
|
|
||||||
checkedNodes = { }
|
checkedNodes = { }
|
||||||
nodes = { }
|
nodes = { }
|
||||||
box = { }
|
box = { }
|
||||||
@@ -126,6 +125,10 @@ return function(startPt, endPt, firstPt, verbose)
|
|||||||
box.ey = math.max(startPt.y, endPt.y)
|
box.ey = math.max(startPt.y, endPt.y)
|
||||||
box.ez = math.max(startPt.z, endPt.z)
|
box.ez = math.max(startPt.z, endPt.z)
|
||||||
|
|
||||||
|
if not Point.inBox(firstPt, box) then
|
||||||
|
error('Starting point is not in leveling area')
|
||||||
|
end
|
||||||
|
|
||||||
if not turtle.pathfind(firstPt) then
|
if not turtle.pathfind(firstPt) then
|
||||||
error('failed to reach starting point')
|
error('failed to reach starting point')
|
||||||
end
|
end
|
||||||
@@ -155,11 +158,13 @@ return function(startPt, endPt, firstPt, verbose)
|
|||||||
|
|
||||||
local node = closestPoint(turtle.point, nodes)
|
local node = closestPoint(turtle.point, nodes)
|
||||||
node = getAdjacentPoint(node)
|
node = getAdjacentPoint(node)
|
||||||
if not turtle.gotoPoint(node) then
|
if not turtle._goto(node) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
until turtle.abort
|
until turtle.isAborted()
|
||||||
|
|
||||||
turtle.resetState()
|
turtle.resetState()
|
||||||
turtle.setMoveCallback(oldCallback)
|
turtle.setMoveCallback(oldCallback)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
|||||||
@@ -1,25 +1,28 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Ansi = require('ansi')
|
local Ansi = require('ansi')
|
||||||
local Config = require('config')
|
|
||||||
local SHA1 = require('sha1')
|
local SHA1 = require('sha1')
|
||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
-- scrap this entire file. don't muck with standard apis
|
local fs = _G.fs
|
||||||
|
local http = _G.http
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
local shell = _ENV.shell
|
||||||
|
|
||||||
local REGISTRY_DIR = 'usr/.registry'
|
local REGISTRY_DIR = 'usr/.registry'
|
||||||
|
|
||||||
|
|
||||||
-- FIX SOMEDAY
|
-- FIX SOMEDAY
|
||||||
function os.registerApp(app, key)
|
local function registerApp(app, key)
|
||||||
|
|
||||||
app.key = SHA1.sha1(key)
|
app.key = SHA1.sha1(key)
|
||||||
Util.writeTable(fs.combine(REGISTRY_DIR, app.key), app)
|
Util.writeTable(fs.combine(REGISTRY_DIR, app.key), app)
|
||||||
os.queueEvent('os_register_app')
|
os.queueEvent('os_register_app')
|
||||||
end
|
end
|
||||||
|
|
||||||
function os.unregisterApp(key)
|
local function unregisterApp(key)
|
||||||
|
|
||||||
local filename = fs.combine(REGISTRY_DIR, SHA1.sha1(key))
|
local filename = fs.combine(REGISTRY_DIR, SHA1.sha1(key))
|
||||||
if fs.exists(filename) then
|
if fs.exists(filename) then
|
||||||
@@ -29,7 +32,7 @@ function os.unregisterApp(key)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local sandboxEnv = Util.shallowCopy(getfenv(1))
|
local sandboxEnv = Util.shallowCopy(_ENV)
|
||||||
setmetatable(sandboxEnv, { __index = _G })
|
setmetatable(sandboxEnv, { __index = _G })
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'App Store')
|
multishell.setTitle(multishell.getCurrent(), 'App Store')
|
||||||
@@ -56,7 +59,7 @@ local sources = {
|
|||||||
|
|
||||||
shell.setDir(APP_DIR)
|
shell.setDir(APP_DIR)
|
||||||
|
|
||||||
function downloadApp(app)
|
local function downloadApp(app)
|
||||||
local h
|
local h
|
||||||
|
|
||||||
if type(app.url) == "table" then
|
if type(app.url) == "table" then
|
||||||
@@ -72,7 +75,7 @@ function downloadApp(app)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function runApp(app, checkExists, ...)
|
local function runApp(app, checkExists, ...)
|
||||||
|
|
||||||
local path, fn
|
local path, fn
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
@@ -173,29 +176,27 @@ local getSourceListing = function(source)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local appPage = UI.Page({
|
local appPage = UI.Page {
|
||||||
menuBar = UI.MenuBar({
|
menuBar = UI.MenuBar {
|
||||||
showBackButton = not pocket,
|
-- showBackButton = not pocket,
|
||||||
buttons = {
|
buttons = {
|
||||||
|
{ text = '\027', event = 'back' },
|
||||||
{ text = 'Install', event = 'install' },
|
{ text = 'Install', event = 'install' },
|
||||||
{ text = 'Run', event = 'run' },
|
{ text = 'Run', event = 'run' },
|
||||||
{ text = 'View', event = 'view' },
|
{ text = 'View', event = 'view' },
|
||||||
{ text = 'Remove', event = 'uninstall', name = 'removeButton' },
|
{ text = 'Remove', event = 'uninstall', name = 'removeButton' },
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
container = UI.Window({
|
container = UI.Window {
|
||||||
x = 2,
|
x = 2, y = 3, ex = -2, ey = -3,
|
||||||
y = 3,
|
viewport = UI.Viewport(),
|
||||||
height = UI.term.height - 3,
|
},
|
||||||
width = UI.term.width - 2,
|
|
||||||
viewport = UI.ViewportWindow(),
|
|
||||||
}),
|
|
||||||
notification = UI.Notification(),
|
notification = UI.Notification(),
|
||||||
accelerators = {
|
accelerators = {
|
||||||
q = 'back',
|
q = 'back',
|
||||||
backspace = 'back',
|
backspace = 'back',
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
|
||||||
function appPage.container.viewport:draw()
|
function appPage.container.viewport:draw()
|
||||||
local app = self.parent.parent.app
|
local app = self.parent.parent.app
|
||||||
@@ -245,7 +246,7 @@ function appPage:eventHandler(event)
|
|||||||
|
|
||||||
elseif event.type == 'uninstall' then
|
elseif event.type == 'uninstall' then
|
||||||
if self.app.runOnly then
|
if self.app.runOnly then
|
||||||
s,m = runApp(self.app, false, 'uninstall')
|
runApp(self.app, false, 'uninstall')
|
||||||
else
|
else
|
||||||
fs.delete(fs.combine(APP_DIR, self.app.name))
|
fs.delete(fs.combine(APP_DIR, self.app.name))
|
||||||
self.notification:success("Uninstalled " .. self.app.name, 3)
|
self.notification:success("Uninstalled " .. self.app.name, 3)
|
||||||
@@ -253,7 +254,7 @@ function appPage:eventHandler(event)
|
|||||||
self.menuBar.removeButton:disable('Remove')
|
self.menuBar.removeButton:disable('Remove')
|
||||||
self.menuBar:draw()
|
self.menuBar:draw()
|
||||||
|
|
||||||
os.unregisterApp(self.app.creator .. '.' .. self.app.name)
|
unregisterApp(self.app.creator .. '.' .. self.app.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif event.type == 'install' then
|
elseif event.type == 'install' then
|
||||||
@@ -277,7 +278,7 @@ function appPage:eventHandler(event)
|
|||||||
category = 'Games'
|
category = 'Games'
|
||||||
end
|
end
|
||||||
|
|
||||||
os.registerApp({
|
registerApp({
|
||||||
run = fs.combine(APP_DIR, self.app.name),
|
run = fs.combine(APP_DIR, self.app.name),
|
||||||
title = self.app.title,
|
title = self.app.title,
|
||||||
category = category,
|
category = category,
|
||||||
@@ -293,35 +294,30 @@ function appPage:eventHandler(event)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local categoryPage = UI.Page({
|
local categoryPage = UI.Page {
|
||||||
menuBar = UI.MenuBar({
|
menuBar = UI.MenuBar {
|
||||||
buttons = {
|
buttons = {
|
||||||
{ text = 'Catalog', event = 'dropdown', dropdown = 'sourceMenu' },
|
{ text = 'Catalog', dropdown = sources },
|
||||||
{ text = 'Category', event = 'dropdown', dropdown = 'categoryMenu' },
|
{ text = 'Category', name = 'categoryButton', dropdown = { } },
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
sourceMenu = UI.DropMenu({
|
grid = UI.ScrollingGrid {
|
||||||
buttons = sources,
|
y = 2, ey = -2,
|
||||||
}),
|
|
||||||
grid = UI.ScrollingGrid({
|
|
||||||
y = 2,
|
|
||||||
height = UI.term.height - 2,
|
|
||||||
columns = {
|
columns = {
|
||||||
{ heading = 'Title', key = 'title' },
|
{ heading = 'Title', key = 'title' },
|
||||||
},
|
},
|
||||||
sortColumn = 'title',
|
sortColumn = 'title',
|
||||||
autospace = true,
|
},
|
||||||
}),
|
|
||||||
statusBar = UI.StatusBar(),
|
statusBar = UI.StatusBar(),
|
||||||
accelerators = {
|
accelerators = {
|
||||||
l = 'lua',
|
l = 'lua',
|
||||||
q = 'quit',
|
q = 'quit',
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
|
||||||
function categoryPage:setCategory(source, name, index)
|
function categoryPage:setCategory(source, name, index)
|
||||||
self.grid.values = { }
|
self.grid.values = { }
|
||||||
for k,v in pairs(source.storeURLs) do
|
for _,v in pairs(source.storeURLs) do
|
||||||
if index == 0 or index == v.catagory then
|
if index == 0 or index == v.catagory then
|
||||||
table.insert(self.grid.values, v)
|
table.insert(self.grid.values, v)
|
||||||
end
|
end
|
||||||
@@ -359,19 +355,17 @@ function categoryPage:setSource(source)
|
|||||||
end
|
end
|
||||||
|
|
||||||
source.categoryMenu = UI.DropMenu({
|
source.categoryMenu = UI.DropMenu({
|
||||||
y = 2,
|
|
||||||
x = 1,
|
|
||||||
buttons = buttons,
|
buttons = buttons,
|
||||||
})
|
})
|
||||||
source.index, source.name = Util.first(source.storeCatagoryNames)
|
source.index, source.name = Util.first(source.storeCatagoryNames)
|
||||||
|
|
||||||
categoryPage:add({
|
categoryPage.menuBar.categoryButton:add({
|
||||||
categoryMenu = source.categoryMenu
|
categoryMenu = source.categoryMenu
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
self.source = source
|
self.source = source
|
||||||
self.categoryMenu = source.categoryMenu
|
self.menuBar.categoryButton.dropmenu = source.categoryMenu
|
||||||
categoryPage:setCategory(source, source.name, source.index)
|
categoryPage:setCategory(source, source.name, source.index)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'Events')
|
multishell.setTitle(multishell.getCurrent(), 'Events')
|
||||||
UI:configure('Events', ...)
|
UI:configure('Events', ...)
|
||||||
|
|
||||||
@@ -123,7 +126,7 @@ Event.addRoutine(function()
|
|||||||
p4 = e[5],
|
p4 = e[5],
|
||||||
p5 = e[6],
|
p5 = e[6],
|
||||||
})
|
})
|
||||||
if #page.grid.values > page.grid.height - 1 then
|
if #page.grid.values > page.grid.height then
|
||||||
table.remove(page.grid.values, #page.grid.values)
|
table.remove(page.grid.values, #page.grid.values)
|
||||||
end
|
end
|
||||||
page.grid:update()
|
page.grid:update()
|
||||||
|
|||||||
@@ -1,24 +1,29 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
|
local Ansi = require('ansi')
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local peripheral = _G.peripheral
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'Devices')
|
multishell.setTitle(multishell.getCurrent(), 'Devices')
|
||||||
|
|
||||||
--[[ -- PeripheralsPage -- ]] --
|
--[[ -- PeripheralsPage -- ]] --
|
||||||
local peripheralsPage = UI.Page {
|
local peripheralsPage = UI.Page {
|
||||||
grid = UI.ScrollingGrid {
|
grid = UI.ScrollingGrid {
|
||||||
|
ey = -2,
|
||||||
columns = {
|
columns = {
|
||||||
{ heading = 'Type', key = 'type' },
|
{ heading = 'Type', key = 'type' },
|
||||||
{ heading = 'Side', key = 'side' },
|
{ heading = 'Side', key = 'side' },
|
||||||
},
|
},
|
||||||
sortColumn = 'type',
|
sortColumn = 'type',
|
||||||
height = UI.term.height - 1,
|
|
||||||
autospace = true,
|
autospace = true,
|
||||||
},
|
},
|
||||||
statusBar = UI.StatusBar {
|
statusBar = UI.StatusBar {
|
||||||
status = 'Select peripheral'
|
values = 'Select peripheral',
|
||||||
},
|
},
|
||||||
accelerators = {
|
accelerators = {
|
||||||
q = 'quit',
|
q = 'quit',
|
||||||
@@ -60,16 +65,17 @@ end
|
|||||||
|
|
||||||
--[[ -- MethodsPage -- ]] --
|
--[[ -- MethodsPage -- ]] --
|
||||||
local methodsPage = UI.Page {
|
local methodsPage = UI.Page {
|
||||||
|
backgroundColor = colors.black,
|
||||||
|
doc = UI.TextArea {
|
||||||
|
backgroundColor = colors.black,
|
||||||
|
x = 2, y = 2, ex = -1, ey = -7,
|
||||||
|
},
|
||||||
grid = UI.ScrollingGrid {
|
grid = UI.ScrollingGrid {
|
||||||
|
y = -6, ey = -2,
|
||||||
columns = {
|
columns = {
|
||||||
{ heading = 'Name', key = 'name', width = UI.term.width }
|
{ heading = 'Name', key = 'name', width = UI.term.width }
|
||||||
},
|
},
|
||||||
sortColumn = 'name',
|
sortColumn = 'name',
|
||||||
height = 7,
|
|
||||||
},
|
|
||||||
viewportConsole = UI.ViewportWindow {
|
|
||||||
y = 8,
|
|
||||||
height = UI.term.height - 8,
|
|
||||||
},
|
},
|
||||||
statusBar = UI.StatusBar {
|
statusBar = UI.StatusBar {
|
||||||
status = 'q to return',
|
status = 'q to return',
|
||||||
@@ -84,8 +90,9 @@ function methodsPage:enable(p)
|
|||||||
|
|
||||||
self.peripheral = p or self.peripheral
|
self.peripheral = p or self.peripheral
|
||||||
|
|
||||||
local p = peripheral.wrap(self.peripheral.side)
|
p = peripheral.wrap(self.peripheral.side)
|
||||||
if p.getDocs then
|
if p.getDocs then
|
||||||
|
-- plethora
|
||||||
self.grid.values = { }
|
self.grid.values = { }
|
||||||
for k,v in pairs(p.getDocs()) do
|
for k,v in pairs(p.getDocs()) do
|
||||||
table.insert(self.grid.values, {
|
table.insert(self.grid.values, {
|
||||||
@@ -94,27 +101,31 @@ function methodsPage:enable(p)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
elseif not p.getAdvancedMethodsData then
|
elseif not p.getAdvancedMethodsData then
|
||||||
|
-- computercraft
|
||||||
self.grid.values = { }
|
self.grid.values = { }
|
||||||
for name,f in pairs(p) do
|
for name in pairs(p) do
|
||||||
table.insert(self.grid.values, {
|
table.insert(self.grid.values, {
|
||||||
name = name,
|
name = name,
|
||||||
noext = true,
|
noext = true,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
-- open peripherals
|
||||||
self.grid.values = p.getAdvancedMethodsData()
|
self.grid.values = p.getAdvancedMethodsData()
|
||||||
for name,f in pairs(self.grid.values) do
|
for name,f in pairs(self.grid.values) do
|
||||||
f.name = name
|
f.name = name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.viewportConsole.offy = 0
|
|
||||||
|
|
||||||
self.grid:update()
|
self.grid:update()
|
||||||
self.grid:setIndex(1)
|
self.grid:setIndex(1)
|
||||||
|
|
||||||
|
self.doc:setText(self:getDocumentation())
|
||||||
|
|
||||||
self.statusBar:setStatus(self.peripheral.type)
|
self.statusBar:setStatus(self.peripheral.type)
|
||||||
UI.Page.enable(self)
|
UI.Page.enable(self)
|
||||||
|
|
||||||
|
self:setFocus(self.grid)
|
||||||
end
|
end
|
||||||
|
|
||||||
function methodsPage:eventHandler(event)
|
function methodsPage:eventHandler(event)
|
||||||
@@ -122,82 +133,62 @@ function methodsPage:eventHandler(event)
|
|||||||
UI:setPage(peripheralsPage)
|
UI:setPage(peripheralsPage)
|
||||||
return true
|
return true
|
||||||
elseif event.type == 'grid_focus_row' then
|
elseif event.type == 'grid_focus_row' then
|
||||||
self.viewportConsole.offy = 0
|
self.doc:setText(self:getDocumentation())
|
||||||
self.viewportConsole:draw()
|
|
||||||
end
|
end
|
||||||
return UI.Page.eventHandler(self, event)
|
return UI.Page.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
|
|
||||||
function methodsPage.viewportConsole:draw()
|
function methodsPage:getDocumentation()
|
||||||
local c = self
|
|
||||||
local method = methodsPage.grid:getSelected()
|
|
||||||
|
|
||||||
c:clear()
|
local method = self.grid:getSelected()
|
||||||
c:setCursorPos(1, 1)
|
|
||||||
|
|
||||||
if method.noext then
|
if method.noext then -- computercraft docs
|
||||||
c.cursorY = 2
|
return 'No documentation'
|
||||||
c:print('No extended Information')
|
|
||||||
return 2
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if method.doc then
|
if method.doc then -- plethora docs
|
||||||
c:print(method.doc, nil, colors.yellow)
|
return Ansi.yellow .. method.doc
|
||||||
c.ymax = c.cursorY + 1
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- open peripherals docs
|
||||||
|
local sb = { }
|
||||||
if method.description then
|
if method.description then
|
||||||
c:print(method.description)
|
table.insert(sb, method.description .. '\n\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
c.cursorY = c.cursorY + 2
|
|
||||||
c.cursorX = 1
|
|
||||||
|
|
||||||
if method.returnTypes ~= '()' then
|
if method.returnTypes ~= '()' then
|
||||||
c:print(method.returnTypes .. ' ', nil, colors.yellow)
|
table.insert(sb, Ansi.yellow .. method.returnTypes .. ' ')
|
||||||
end
|
end
|
||||||
c:print(method.name, nil, colors.black)
|
table.insert(sb, Ansi.blue .. method.name .. Ansi.reset .. '(')
|
||||||
c:print('(')
|
|
||||||
|
|
||||||
local maxArgLen = 1
|
|
||||||
|
|
||||||
for k,arg in ipairs(method.args) do
|
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
|
if arg.optional then
|
||||||
argName = string.format('[%s]', arg.name)
|
table.insert(sb, Ansi.orange .. string.format('[%s]', arg.name))
|
||||||
fg = colors.orange
|
else
|
||||||
|
table.insert(sb, Ansi.green .. arg.name)
|
||||||
end
|
end
|
||||||
c:print(argName, nil, fg)
|
|
||||||
if k < #method.args then
|
if k < #method.args then
|
||||||
c:print(', ')
|
table.insert(sb, ',')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
c:print(')')
|
table.insert(sb, Ansi.reset .. ')')
|
||||||
|
|
||||||
c.cursorY = c.cursorY + 1
|
|
||||||
|
|
||||||
|
Util.filterInplace(method.args, function(a) return #a.description > 0 end)
|
||||||
if #method.args > 0 then
|
if #method.args > 0 then
|
||||||
for _,arg in ipairs(method.args) do
|
table.insert(sb, '\n\n')
|
||||||
if #arg.description > 0 then
|
for k,arg in ipairs(method.args) do
|
||||||
c.cursorY = c.cursorY + 1
|
if arg.optional then
|
||||||
c.cursorX = 1
|
table.insert(sb, Ansi.orange)
|
||||||
local fg = colors.green
|
else
|
||||||
if arg.optional then
|
table.insert(sb, Ansi.green)
|
||||||
fg = colors.orange
|
end
|
||||||
end
|
table.insert(sb, arg.name .. Ansi.reset .. ': ' .. arg.description)
|
||||||
c:print(arg.name .. ': ', nil, fg)
|
if k ~= #method.args then
|
||||||
c.cursorX = maxArgLen + 3
|
table.insert(sb, '\n\n')
|
||||||
c:print(arg.description, nil, nil, maxArgLen + 3)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return table.concat(sb)
|
||||||
c.ymax = c.cursorY + 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Event.on('peripheral', function()
|
Event.on('peripheral', function()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Config = require('config')
|
local Config = require('config')
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
@@ -6,6 +6,12 @@ local Socket = require('socket')
|
|||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
local fs = _G.fs
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
local shell = _ENV.shell
|
||||||
|
|
||||||
local GROUPS_PATH = 'usr/groups'
|
local GROUPS_PATH = 'usr/groups'
|
||||||
local SCRIPTS_PATH = 'usr/etc/scripts'
|
local SCRIPTS_PATH = 'usr/etc/scripts'
|
||||||
|
|
||||||
@@ -26,7 +32,7 @@ if UI.term.width % 2 ~= 0 then
|
|||||||
width = width + 1
|
width = width + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function processVariables(script)
|
local function processVariables(script)
|
||||||
|
|
||||||
local fn = loadstring('return ' .. config.variables)
|
local fn = loadstring('return ' .. config.variables)
|
||||||
if fn then
|
if fn then
|
||||||
@@ -40,7 +46,7 @@ function processVariables(script)
|
|||||||
return script
|
return script
|
||||||
end
|
end
|
||||||
|
|
||||||
function invokeScript(computer, scriptName)
|
local function invokeScript(computer, scriptName)
|
||||||
|
|
||||||
local script = Util.readFile(scriptName)
|
local script = Util.readFile(scriptName)
|
||||||
if not script then
|
if not script then
|
||||||
@@ -74,7 +80,7 @@ function invokeScript(computer, scriptName)
|
|||||||
socket:close()
|
socket:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function runScript(computerOrGroup, scriptName)
|
local function runScript(computerOrGroup, scriptName)
|
||||||
if computerOrGroup.id then
|
if computerOrGroup.id then
|
||||||
invokeScript(computerOrGroup, scriptName)
|
invokeScript(computerOrGroup, scriptName)
|
||||||
else
|
else
|
||||||
@@ -302,7 +308,6 @@ function editorPage:enable()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function editorPage.grid2:draw()
|
function editorPage.grid2:draw()
|
||||||
|
|
||||||
getActiveComputers(self.values)
|
getActiveComputers(self.values)
|
||||||
|
|
||||||
for k in pairs(editorPage.grid1.values) do
|
for k in pairs(editorPage.grid1.values) do
|
||||||
@@ -314,7 +319,6 @@ function editorPage.grid2:draw()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function editorPage:eventHandler(event)
|
function editorPage:eventHandler(event)
|
||||||
|
|
||||||
if event.type == 'back' then
|
if event.type == 'back' then
|
||||||
UI:setPage(groupsPage)
|
UI:setPage(groupsPage)
|
||||||
|
|
||||||
@@ -341,18 +345,17 @@ function editorPage:eventHandler(event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function nameDialog(f)
|
local function nameDialog(f)
|
||||||
local dialog = UI.Dialog({
|
local dialog = UI.Dialog {
|
||||||
-- x = (UI.term.width - 28) / 2,
|
|
||||||
width = 22,
|
width = 22,
|
||||||
height = 6,
|
height = 6,
|
||||||
title = 'Enter Name',
|
title = 'Enter Name',
|
||||||
form = UI.Form {
|
form = UI.Form {
|
||||||
x = 2, ex = -2, y = 2,
|
x = 2, ex = -2, y = 2,
|
||||||
textEntry = UI.TextEntry({ y = 2, width = 20, limit = 20 })
|
textEntry = UI.TextEntry { y = 2, width = 20, limit = 20 },
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
|
||||||
dialog.eventHandler = function(self, event)
|
function dialog:eventHandler(event)
|
||||||
if event.type == 'form_complete' then
|
if event.type == 'form_complete' then
|
||||||
local name = self.form.textEntry.value
|
local name = self.form.textEntry.value
|
||||||
if name then
|
if name then
|
||||||
@@ -459,11 +462,6 @@ function mainPage:eventHandler(event)
|
|||||||
|
|
||||||
elseif event.type == 'toggle' then
|
elseif event.type == 'toggle' then
|
||||||
config.showGroups = not config.showGroups
|
config.showGroups = not config.showGroups
|
||||||
local text = 'Computers'
|
|
||||||
if config.showGroups then
|
|
||||||
text = 'Groups'
|
|
||||||
end
|
|
||||||
-- self.statusBar.toggleButton.text = text
|
|
||||||
self:draw()
|
self:draw()
|
||||||
|
|
||||||
Config.update('script', config)
|
Config.update('script', config)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Config = require('config')
|
local Config = require('config')
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
@@ -8,6 +8,14 @@ local Terminal = require('terminal')
|
|||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
local fs = _G.fs
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local network = _G.network
|
||||||
|
local os = _G.os
|
||||||
|
local shell = _ENV.shell
|
||||||
|
local term = _G.term
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'Turtles')
|
multishell.setTitle(multishell.getCurrent(), 'Turtles')
|
||||||
UI.Button.defaults.focusIndicator = ' '
|
UI.Button.defaults.focusIndicator = ' '
|
||||||
UI:configure('Turtles', ...)
|
UI:configure('Turtles', ...)
|
||||||
@@ -27,15 +35,7 @@ local options = {
|
|||||||
local SCRIPTS_PATH = 'usr/etc/scripts'
|
local SCRIPTS_PATH = 'usr/etc/scripts'
|
||||||
|
|
||||||
local nullTerm = Terminal.getNullTerm(term.current())
|
local nullTerm = Terminal.getNullTerm(term.current())
|
||||||
local turtles = { }
|
|
||||||
local socket
|
local socket
|
||||||
local policies = {
|
|
||||||
{ label = 'none' },
|
|
||||||
{ label = 'digOnly' },
|
|
||||||
{ label = 'attackOnly' },
|
|
||||||
{ label = 'digAttack' },
|
|
||||||
{ label = 'turtleSafe' },
|
|
||||||
}
|
|
||||||
|
|
||||||
local page = UI.Page {
|
local page = UI.Page {
|
||||||
coords = UI.Window {
|
coords = UI.Window {
|
||||||
@@ -125,7 +125,8 @@ local page = UI.Page {
|
|||||||
fn = 'turtle.turnRight',
|
fn = 'turtle.turnRight',
|
||||||
},
|
},
|
||||||
info = UI.TextArea {
|
info = UI.TextArea {
|
||||||
x = 2, y = 9
|
x = 2, y = 9,
|
||||||
|
inactive = true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -142,7 +143,7 @@ function page:enable(turtle)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function page:runFunction(script, nowrap)
|
function page:runFunction(script, nowrap)
|
||||||
for i = 1, 2 do
|
for _ = 1, 2 do
|
||||||
if not socket then
|
if not socket then
|
||||||
socket = Socket.connect(self.turtle.id, 161)
|
socket = Socket.connect(self.turtle.id, 161)
|
||||||
end
|
end
|
||||||
@@ -210,12 +211,6 @@ function page.tabs.inventory:draw()
|
|||||||
v.selected = true
|
v.selected = true
|
||||||
end
|
end
|
||||||
if v.id then
|
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
|
|
||||||
v.id = itemDB:getName(v)
|
v.id = itemDB:getName(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -303,14 +298,6 @@ function page.statusBar:draw()
|
|||||||
UI.StatusBar.draw(self)
|
UI.StatusBar.draw(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function page.tabs.tabBar:selectTab(tabTitle)
|
|
||||||
if tabTitle then
|
|
||||||
config.tab = tabTitle
|
|
||||||
Config.update('Turtles', config)
|
|
||||||
return UI.TabBar.selectTab(self, tabTitle)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function page:showBlocks()
|
function page:showBlocks()
|
||||||
|
|
||||||
local script = [[
|
local script = [[
|
||||||
@@ -333,6 +320,11 @@ end
|
|||||||
function page:eventHandler(event)
|
function page:eventHandler(event)
|
||||||
if event.type == 'quit' then
|
if event.type == 'quit' then
|
||||||
UI:exitPullEvents()
|
UI:exitPullEvents()
|
||||||
|
|
||||||
|
elseif event.type == 'tab_select' then
|
||||||
|
config.tab = event.button.text
|
||||||
|
Config.update('Turtles', config)
|
||||||
|
|
||||||
elseif event.type == 'button_press' then
|
elseif event.type == 'button_press' then
|
||||||
if event.button.fn then
|
if event.button.fn then
|
||||||
self:runFunction(event.button.fn, event.button.nowrap)
|
self:runFunction(event.button.fn, event.button.nowrap)
|
||||||
@@ -356,7 +348,7 @@ if not Util.getOptions(options, { ... }, true) then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if options.turtle.value >= 0 then
|
if options.turtle.value >= 0 then
|
||||||
for i = 1, 10 do
|
for _ = 1, 10 do
|
||||||
page.turtle = _G.network[options.turtle.value]
|
page.turtle = _G.network[options.turtle.value]
|
||||||
if page.turtle then
|
if page.turtle then
|
||||||
break
|
break
|
||||||
@@ -374,18 +366,10 @@ Event.onInterval(1, function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
UI:setPage(page)
|
if config.tab then
|
||||||
|
page.tabs.tabBar:selectTab(config.tab)
|
||||||
local lookup = {
|
|
||||||
Run = page.tabs.scripts,
|
|
||||||
Select = page.tabs.turtles,
|
|
||||||
Inv = page.tabs.inventory,
|
|
||||||
-- Mod = page.tabs.policy,
|
|
||||||
Action = page.tabs.action,
|
|
||||||
}
|
|
||||||
|
|
||||||
if lookup[options.tab.value] then
|
|
||||||
page.tabs:activateTab(lookup[options.tab.value])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
UI:setPage(page)
|
||||||
|
|
||||||
UI:pullEvents()
|
UI:pullEvents()
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
Base64 = require('base64')
|
local Base64 = require('base64')
|
||||||
|
|
||||||
|
local http = _G.http
|
||||||
|
local os = _G.os
|
||||||
|
local shell = _ENV.shell
|
||||||
|
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
|
|
||||||
|
|||||||
1639
apps/builder.lua
1639
apps/builder.lua
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1055
apps/crafter.lua
Normal file
1055
apps/crafter.lua
Normal file
File diff suppressed because it is too large
Load Diff
414
apps/edit.lua
414
apps/edit.lua
@@ -1,4 +1,13 @@
|
|||||||
shell.setCompletionFunction(shell.getRunningProgram(), function(shell, index, text)
|
local colors = _G.colors
|
||||||
|
local fs = _G.fs
|
||||||
|
local keys = _G.keys
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
local shell = _ENV.shell
|
||||||
|
local term = _G.term
|
||||||
|
local textutils = _G.textutils
|
||||||
|
|
||||||
|
shell.setCompletionFunction(shell.getRunningProgram(), function(_, index, text)
|
||||||
if index == 1 then
|
if index == 1 then
|
||||||
return fs.complete(text, shell.dir(), true, false)
|
return fs.complete(text, shell.dir(), true, false)
|
||||||
end
|
end
|
||||||
@@ -17,7 +26,7 @@ if fs.exists(sPath) and fs.isDir(sPath) then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if multishell then
|
if multishell then
|
||||||
multishell.setTitle(multishell.getCurrent(), sPath)
|
multishell.setTitle(multishell.getCurrent(), fs.getName(sPath))
|
||||||
end
|
end
|
||||||
|
|
||||||
local x, y = 1, 1
|
local x, y = 1, 1
|
||||||
@@ -26,43 +35,38 @@ local scrollX = 0
|
|||||||
local scrollY = 0
|
local scrollY = 0
|
||||||
local lastPos = { x = 1, y = 1 }
|
local lastPos = { x = 1, y = 1 }
|
||||||
local tLines = { }
|
local tLines = { }
|
||||||
|
local input = { pressed = { } }
|
||||||
local bRunning = true
|
local bRunning = true
|
||||||
local sStatus = ""
|
local sStatus = ""
|
||||||
local isError
|
local isError
|
||||||
local fileInfo
|
local fileInfo
|
||||||
|
local lastAction
|
||||||
|
|
||||||
local dirty = { y = 1, ey = h }
|
local dirty = { y = 1, ey = h }
|
||||||
local mark = { anchor, active, continue }
|
local mark = { }
|
||||||
local keyboard
|
|
||||||
local searchPattern
|
local searchPattern
|
||||||
local undo = { chain = { }, pointer = 0 }
|
local undo = { chain = { }, pointer = 0 }
|
||||||
local complete = { }
|
local complete = { }
|
||||||
|
local clipboard
|
||||||
|
|
||||||
if not clipboard then
|
-- do we need a clipboard shim
|
||||||
_G.clipboard = { internal, data }
|
if not multishell or not multishell.hook then -- is this OpusOS ?
|
||||||
clipboard.shim = true
|
if _G.clipboard then -- has it been installed already
|
||||||
|
clipboard = _G.clipboard
|
||||||
|
else
|
||||||
|
clipboard = { }
|
||||||
|
|
||||||
function clipboard.setData(data)
|
function clipboard.setData(data)
|
||||||
clipboard.data = data
|
clipboard.data = data
|
||||||
if data then
|
|
||||||
clipboard.useInternal(true)
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function clipboard.getText()
|
function clipboard.getText()
|
||||||
if clipboard.data then
|
if clipboard.data then
|
||||||
return tostring(clipboard.data)
|
return tostring(clipboard.data)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function clipboard.isInternal()
|
_G.clipboard = clipboard
|
||||||
return clipboard.internal
|
|
||||||
end
|
|
||||||
|
|
||||||
function clipboard.useInternal(mode)
|
|
||||||
if mode ~= clipboard.mode then
|
|
||||||
clipboard.internal = mode
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -110,7 +114,7 @@ local keyMapping = {
|
|||||||
[ 'control-up' ] = 'scroll_up',
|
[ 'control-up' ] = 'scroll_up',
|
||||||
[ 'scrollDown' ] = 'scroll_down',
|
[ 'scrollDown' ] = 'scroll_down',
|
||||||
[ 'control-down' ] = 'scroll_down',
|
[ 'control-down' ] = 'scroll_down',
|
||||||
[ 'mouse_click' ] = 'goto',
|
[ 'mouse_click' ] = 'go_to',
|
||||||
[ 'control-l' ] = 'goto_line',
|
[ 'control-l' ] = 'goto_line',
|
||||||
|
|
||||||
-- marking
|
-- marking
|
||||||
@@ -139,8 +143,7 @@ local keyMapping = {
|
|||||||
-- copy/paste
|
-- copy/paste
|
||||||
[ 'control-x' ] = 'cut',
|
[ 'control-x' ] = 'cut',
|
||||||
[ 'control-c' ] = 'copy',
|
[ 'control-c' ] = 'copy',
|
||||||
[ 'control-v' ] = 'paste',
|
[ 'shift-paste' ] = 'paste_internal',
|
||||||
[ 'control-t' ] = 'toggle_clipboard',
|
|
||||||
|
|
||||||
-- file
|
-- file
|
||||||
[ 'control-s' ] = 'save',
|
[ 'control-s' ] = 'save',
|
||||||
@@ -155,7 +158,7 @@ local keyMapping = {
|
|||||||
-- misc
|
-- misc
|
||||||
[ 'control-g' ] = 'status',
|
[ 'control-g' ] = 'status',
|
||||||
[ 'control-r' ] = 'refresh',
|
[ 'control-r' ] = 'refresh',
|
||||||
[ 'leftCtrl' ] = 'menu',
|
[ 'control' ] = 'menu',
|
||||||
}
|
}
|
||||||
|
|
||||||
local messages = {
|
local messages = {
|
||||||
@@ -246,7 +249,7 @@ local function save( _sPath )
|
|||||||
local function innerSave()
|
local function innerSave()
|
||||||
file = fs.open( _sPath, "w" )
|
file = fs.open( _sPath, "w" )
|
||||||
if file then
|
if file then
|
||||||
for n, sLine in ipairs( tLines ) do
|
for _,sLine in ipairs( tLines ) do
|
||||||
file.write(sLine .. "\n")
|
file.write(sLine .. "\n")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -299,8 +302,8 @@ local function writeHighlighted(sLine, ny)
|
|||||||
text = '',
|
text = '',
|
||||||
}
|
}
|
||||||
|
|
||||||
local function tryWrite(sLine, regex, fgcolor)
|
local function tryWrite(line, regex, fgcolor)
|
||||||
local match = sLine:match(regex)
|
local match = line:match(regex)
|
||||||
if match then
|
if match then
|
||||||
local fg
|
local fg
|
||||||
if type(fgcolor) == "string" then
|
if type(fgcolor) == "string" then
|
||||||
@@ -310,7 +313,7 @@ local function writeHighlighted(sLine, ny)
|
|||||||
end
|
end
|
||||||
buffer.text = buffer.text .. match
|
buffer.text = buffer.text .. match
|
||||||
buffer.fg = buffer.fg .. string.rep(fg, #match)
|
buffer.fg = buffer.fg .. string.rep(fg, #match)
|
||||||
return sLine:sub(#match + 1)
|
return line:sub(#match + 1)
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -388,18 +391,13 @@ local function redraw()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not (w < 32 and #sStatus > 0) then
|
if not (w < 32 and #sStatus > 0) then
|
||||||
local clipboardIndicator = 'S'
|
|
||||||
if clipboard.isInternal() then
|
|
||||||
clipboardIndicator = 'I'
|
|
||||||
end
|
|
||||||
|
|
||||||
local modifiedIndicator = ' '
|
local modifiedIndicator = ' '
|
||||||
if undo.chain[1] then
|
if undo.chain[1] then
|
||||||
modifiedIndicator = '*'
|
modifiedIndicator = '*'
|
||||||
end
|
end
|
||||||
|
|
||||||
local str = string.format(' %d:%d %s%s',
|
local str = string.format(' %d:%d %s',
|
||||||
y, x, clipboardIndicator, modifiedIndicator)
|
y, x, modifiedIndicator)
|
||||||
term.setTextColor(color.highlightColor)
|
term.setTextColor(color.highlightColor)
|
||||||
term.setBackgroundColor(colors.gray)
|
term.setBackgroundColor(colors.gray)
|
||||||
term.setCursorPos(w - #str + 1, h)
|
term.setCursorPos(w - #str + 1, h)
|
||||||
@@ -434,15 +432,15 @@ local function hacky_read()
|
|||||||
local _oldSetCursorPos = term.setCursorPos
|
local _oldSetCursorPos = term.setCursorPos
|
||||||
local _oldGetCursorPos = term.getCursorPos
|
local _oldGetCursorPos = term.getCursorPos
|
||||||
|
|
||||||
term.setCursorPos = function(x, y)
|
term.setCursorPos = function(cx)
|
||||||
return _oldSetCursorPos(x, h)
|
return _oldSetCursorPos(cx, h)
|
||||||
end
|
end
|
||||||
term.getCursorPos = function()
|
term.getCursorPos = function()
|
||||||
local x, y = _oldGetCursorPos()
|
local cx = _oldGetCursorPos()
|
||||||
return x, 1
|
return cx, 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local s, m = pcall(function() return read() end)
|
local s, m = pcall(function() return _G.read() end)
|
||||||
term.setCursorPos = _oldSetCursorPos
|
term.setCursorPos = _oldSetCursorPos
|
||||||
term.getCursorPos = _oldGetCursorPos
|
term.getCursorPos = _oldGetCursorPos
|
||||||
if s then
|
if s then
|
||||||
@@ -465,7 +463,7 @@ local __actions = {
|
|||||||
term.write(prompt)
|
term.write(prompt)
|
||||||
local str = hacky_read()
|
local str = hacky_read()
|
||||||
term.setCursorBlink(true)
|
term.setCursorBlink(true)
|
||||||
keyboard.shift, keyboard.control = false, false
|
input:reset()
|
||||||
term.setCursorPos(x - scrollX, y - scrollY)
|
term.setCursorPos(x - scrollX, y - scrollY)
|
||||||
actions.dirty_line(scrollY + h)
|
actions.dirty_line(scrollY + h)
|
||||||
return str
|
return str
|
||||||
@@ -485,13 +483,6 @@ local __actions = {
|
|||||||
addUndo = function(entry)
|
addUndo = function(entry)
|
||||||
local last = undo.chain[#undo.chain]
|
local last = undo.chain[#undo.chain]
|
||||||
if last and last.action == entry.action then
|
if last and last.action == entry.action then
|
||||||
--[[
|
|
||||||
debug('---')
|
|
||||||
debug(last)
|
|
||||||
debug(last.args)
|
|
||||||
debug(entry)
|
|
||||||
debug(entry.args)
|
|
||||||
]]--
|
|
||||||
if last.action == 'deleteText' then
|
if last.action == 'deleteText' then
|
||||||
if last.args[3] == entry.args[1] and
|
if last.args[3] == entry.args[1] and
|
||||||
last.args[4] == entry.args[2] then
|
last.args[4] == entry.args[2] then
|
||||||
@@ -512,7 +503,7 @@ local __actions = {
|
|||||||
end,
|
end,
|
||||||
|
|
||||||
autocomplete = function()
|
autocomplete = function()
|
||||||
if keyboard.lastAction ~= 'autocomplete' or not complete.results then
|
if lastAction ~= 'autocomplete' or not complete.results then
|
||||||
local sLine = tLines[y]:sub(1, x - 1)
|
local sLine = tLines[y]:sub(1, x - 1)
|
||||||
local nStartPos = sLine:find("[a-zA-Z0-9_%.]+$")
|
local nStartPos = sLine:find("[a-zA-Z0-9_%.]+$")
|
||||||
if nStartPos then
|
if nStartPos then
|
||||||
@@ -575,7 +566,7 @@ local __actions = {
|
|||||||
goto_line = function()
|
goto_line = function()
|
||||||
local lineNo = tonumber(actions.input('Line: '))
|
local lineNo = tonumber(actions.input('Line: '))
|
||||||
if lineNo then
|
if lineNo then
|
||||||
actions.goto(1, lineNo)
|
actions.go_to(1, lineNo)
|
||||||
else
|
else
|
||||||
setStatus('Invalid line number')
|
setStatus('Invalid line number')
|
||||||
end
|
end
|
||||||
@@ -593,9 +584,9 @@ local __actions = {
|
|||||||
if ny < y or ny == y and nx <= x then
|
if ny < y or ny == y and nx <= x then
|
||||||
setStatus(messages.wrapped)
|
setStatus(messages.wrapped)
|
||||||
end
|
end
|
||||||
actions.goto(nx, ny)
|
actions.go_to(nx, ny)
|
||||||
actions.mark_to(nx + #pattern, ny)
|
actions.mark_to(nx + #pattern, ny)
|
||||||
actions.goto(nx, ny)
|
actions.go_to(nx, ny)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
sx = 1
|
sx = 1
|
||||||
@@ -625,7 +616,7 @@ local __actions = {
|
|||||||
if bReadOnly then
|
if bReadOnly then
|
||||||
setError("Access denied")
|
setError("Access denied")
|
||||||
else
|
else
|
||||||
local ok, err = save(sPath)
|
local ok = save(sPath)
|
||||||
if ok then
|
if ok then
|
||||||
setStatus('"%s" %dL, %dC written',
|
setStatus('"%s" %dL, %dC written',
|
||||||
fileInfo.path, #tLines, fs.getSize(fileInfo.abspath))
|
fileInfo.path, #tLines, fs.getSize(fileInfo.abspath))
|
||||||
@@ -641,7 +632,7 @@ local __actions = {
|
|||||||
|
|
||||||
run = function()
|
run = function()
|
||||||
local sTempPath = "/.temp"
|
local sTempPath = "/.temp"
|
||||||
local ok, err = save(sTempPath)
|
local ok = save(sTempPath)
|
||||||
if ok then
|
if ok then
|
||||||
local nTask = shell.openTab(sTempPath)
|
local nTask = shell.openTab(sTempPath)
|
||||||
if nTask then
|
if nTask then
|
||||||
@@ -732,7 +723,7 @@ local __actions = {
|
|||||||
|
|
||||||
mark_to = function(nx, ny)
|
mark_to = function(nx, ny)
|
||||||
actions.mark_begin()
|
actions.mark_begin()
|
||||||
actions.goto(nx, ny)
|
actions.go_to(nx, ny)
|
||||||
actions.mark_finish()
|
actions.mark_finish()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -795,9 +786,7 @@ local __actions = {
|
|||||||
actions.dirty_all()
|
actions.dirty_all()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
setCursor = function(newX, newY)
|
setCursor = function()
|
||||||
local oldX, oldY = lastPos.x, lastPos.y
|
|
||||||
|
|
||||||
lastPos.x = x
|
lastPos.x = x
|
||||||
lastPos.y = y
|
lastPos.y = y
|
||||||
|
|
||||||
@@ -806,27 +795,23 @@ local __actions = {
|
|||||||
|
|
||||||
if screenX < 1 then
|
if screenX < 1 then
|
||||||
scrollX = x - 1
|
scrollX = x - 1
|
||||||
screenX = 1
|
|
||||||
actions.dirty_all()
|
actions.dirty_all()
|
||||||
elseif screenX > w then
|
elseif screenX > w then
|
||||||
scrollX = x - w
|
scrollX = x - w
|
||||||
screenX = w
|
|
||||||
actions.dirty_all()
|
actions.dirty_all()
|
||||||
end
|
end
|
||||||
|
|
||||||
if screenY < 1 then
|
if screenY < 1 then
|
||||||
scrollY = y - 1
|
scrollY = y - 1
|
||||||
screenY = 1
|
|
||||||
actions.dirty_all()
|
actions.dirty_all()
|
||||||
elseif screenY > h - 1 then
|
elseif screenY > h - 1 then
|
||||||
scrollY = y - (h - 1)
|
scrollY = y - (h - 1)
|
||||||
screenY = h - 1
|
|
||||||
actions.dirty_all()
|
actions.dirty_all()
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
top = function()
|
top = function()
|
||||||
actions.goto(1, 1)
|
actions.go_to(1, 1)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
bottom = function()
|
bottom = function()
|
||||||
@@ -856,11 +841,11 @@ local __actions = {
|
|||||||
end,
|
end,
|
||||||
|
|
||||||
pageUp = function()
|
pageUp = function()
|
||||||
actions.goto(x, y - (h - 1))
|
actions.go_to(x, y - (h - 1))
|
||||||
end,
|
end,
|
||||||
|
|
||||||
pageDown = function()
|
pageDown = function()
|
||||||
actions.goto(x, y + (h - 1))
|
actions.go_to(x, y + (h - 1))
|
||||||
end,
|
end,
|
||||||
|
|
||||||
home = function()
|
home = function()
|
||||||
@@ -966,7 +951,7 @@ local __actions = {
|
|||||||
|
|
||||||
local front = tLines[sy]:sub(1, sx - 1)
|
local front = tLines[sy]:sub(1, sx - 1)
|
||||||
local back = tLines[ey]:sub(ex, #tLines[ey])
|
local back = tLines[ey]:sub(ex, #tLines[ey])
|
||||||
for k = 2, ey - sy + 1 do
|
for _ = 2, ey - sy + 1 do
|
||||||
table.remove(tLines, y + 1)
|
table.remove(tLines, y + 1)
|
||||||
end
|
end
|
||||||
tLines[y] = front .. back
|
tLines[y] = front .. back
|
||||||
@@ -981,18 +966,18 @@ local __actions = {
|
|||||||
local count = 0
|
local count = 0
|
||||||
local lines = { }
|
local lines = { }
|
||||||
|
|
||||||
for y = csy, cey do
|
for cy = csy, cey do
|
||||||
local line = tLines[y]
|
local line = tLines[cy]
|
||||||
if line then
|
if line then
|
||||||
local x = 1
|
local cx = 1
|
||||||
local ex = #line
|
local ex = #line
|
||||||
if y == csy then
|
if cy == csy then
|
||||||
x = csx
|
cx = csx
|
||||||
end
|
end
|
||||||
if y == cey then
|
if cy == cey then
|
||||||
ex = cex - 1
|
ex = cex - 1
|
||||||
end
|
end
|
||||||
local str = line:sub(x, ex)
|
local str = line:sub(cx, ex)
|
||||||
count = count + #str
|
count = count + #str
|
||||||
table.insert(lines, str)
|
table.insert(lines, str)
|
||||||
end
|
end
|
||||||
@@ -1041,23 +1026,14 @@ local __actions = {
|
|||||||
actions.insertText(x, y, ch)
|
actions.insertText(x, y, ch)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
toggle_clipboard = function()
|
|
||||||
if clipboard.shim then
|
|
||||||
clipboard.setInternal(not clipboard.internal)
|
|
||||||
end
|
|
||||||
if clipboard.isInternal() then
|
|
||||||
setStatus('Using internal clipboard')
|
|
||||||
else
|
|
||||||
setStatus('Using system clipboard')
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
copy_marked = function()
|
copy_marked = function()
|
||||||
local text, size =
|
local text = actions.copyText(mark.x, mark.y, mark.ex, mark.ey)
|
||||||
actions.copyText(mark.x, mark.y, mark.ex, mark.ey)
|
if clipboard then
|
||||||
clipboard.setData(text)
|
clipboard.setData(text)
|
||||||
setStatus('%d chars copied', size)
|
else
|
||||||
clipboard.useInternal(true)
|
os.queueEvent('clipboard_copy', text)
|
||||||
|
end
|
||||||
|
setStatus('shift-^v to paste')
|
||||||
end,
|
end,
|
||||||
|
|
||||||
cut = function()
|
cut = function()
|
||||||
@@ -1078,9 +1054,6 @@ local __actions = {
|
|||||||
if mark.active then
|
if mark.active then
|
||||||
actions.delete()
|
actions.delete()
|
||||||
end
|
end
|
||||||
if clipboard.isInternal() then
|
|
||||||
text = clipboard.getText()
|
|
||||||
end
|
|
||||||
if text then
|
if text then
|
||||||
actions.insertText(x, y, text)
|
actions.insertText(x, y, text)
|
||||||
setStatus('%d chars added', #text)
|
setStatus('%d chars added', #text)
|
||||||
@@ -1089,7 +1062,13 @@ local __actions = {
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
goto = function(cx, cy)
|
paste_internal = function()
|
||||||
|
if clipboard then
|
||||||
|
actions.paste(clipboard.getText())
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
go_to = function(cx, cy)
|
||||||
y = math.min(math.max(cy, 1), #tLines)
|
y = math.min(math.max(cy, 1), #tLines)
|
||||||
x = math.min(math.max(cx, 1), #tLines[y] + 1)
|
x = math.min(math.max(cx, 1), #tLines[y] + 1)
|
||||||
end,
|
end,
|
||||||
@@ -1114,116 +1093,158 @@ local __actions = {
|
|||||||
|
|
||||||
actions = __actions
|
actions = __actions
|
||||||
|
|
||||||
-- Actual program functionality begins
|
local modifiers = {
|
||||||
load(sPath)
|
[ keys.leftCtrl ] = true,
|
||||||
|
[ keys.rightCtrl ] = true,
|
||||||
|
[ keys.leftShift ] = true,
|
||||||
|
[ keys.rightShift ] = true,
|
||||||
|
[ keys.leftAlt ] = true,
|
||||||
|
[ keys.rightAlt ] = true,
|
||||||
|
}
|
||||||
|
|
||||||
term.setCursorBlink(true)
|
function input:modifierPressed()
|
||||||
redraw()
|
return self.pressed[keys.leftCtrl] or
|
||||||
|
self.pressed[keys.rightCtrl] or
|
||||||
|
self.pressed[keys.leftAlt] or
|
||||||
|
self.pressed[keys.rightAlt]
|
||||||
|
end
|
||||||
|
|
||||||
if not keyboard then
|
function input:toCode(ch, code)
|
||||||
keyboard = { control, shift, combo }
|
local result = { }
|
||||||
|
|
||||||
function keyboard:translate(event, code)
|
if self.pressed[keys.leftCtrl] or self.pressed[keys.rightCtrl] then
|
||||||
if event == 'key' then
|
table.insert(result, 'control')
|
||||||
local ch = keys.getName(code)
|
end
|
||||||
if ch then
|
|
||||||
|
|
||||||
if code == keys.leftCtrl or code == keys.rightCtrl then
|
if self.pressed[keys.leftAlt] or self.pressed[keys.rightAlt] then
|
||||||
self.control = true
|
table.insert(result, 'alt')
|
||||||
self.combo = false
|
end
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if code == keys.leftShift or code == keys.rightShift then
|
if self.pressed[keys.leftShift] or self.pressed[keys.rightShift] then
|
||||||
self.shift = true
|
if code and modifiers[code] then
|
||||||
self.combo = false
|
table.insert(result, 'shift')
|
||||||
return
|
elseif #ch == 1 then
|
||||||
end
|
table.insert(result, ch:upper())
|
||||||
|
else
|
||||||
if self.shift then
|
table.insert(result, 'shift')
|
||||||
if #ch > 1 then
|
table.insert(result, ch)
|
||||||
ch = 'shift-' .. ch
|
|
||||||
elseif self.control then
|
|
||||||
-- will create control-X
|
|
||||||
-- better than shift-control-x
|
|
||||||
ch = ch:upper()
|
|
||||||
end
|
|
||||||
self.combo = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.control then
|
|
||||||
ch = 'control-' .. ch
|
|
||||||
self.combo = true
|
|
||||||
-- even return numbers such as
|
|
||||||
-- control-seven
|
|
||||||
return ch
|
|
||||||
end
|
|
||||||
|
|
||||||
-- filter out characters that will be processed in
|
|
||||||
-- the subsequent char event
|
|
||||||
if ch and #ch > 1 and (code < 2 or code > 11) then
|
|
||||||
return ch
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif event == 'key_up' then
|
|
||||||
|
|
||||||
if code == keys.leftCtrl or code == keys.rightCtrl then
|
|
||||||
self.control = false
|
|
||||||
elseif code == keys.leftShift or code == keys.rightShift then
|
|
||||||
self.shift = false
|
|
||||||
else
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- only send through the shift / control event if it wasn't
|
|
||||||
-- used in combination with another event
|
|
||||||
if not self.combo then
|
|
||||||
return keys.getName(code)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif event == 'char' then
|
|
||||||
if not self.control then
|
|
||||||
self.combo = true
|
|
||||||
return event
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif event == 'mouse_click' then
|
|
||||||
|
|
||||||
local buttons = { 'mouse_click', 'mouse_rightclick', 'mouse_doubleclick' }
|
|
||||||
|
|
||||||
self.combo = true
|
|
||||||
if self.shift then
|
|
||||||
return 'shift-' .. buttons[code]
|
|
||||||
end
|
|
||||||
return buttons[code]
|
|
||||||
|
|
||||||
elseif event == "mouse_scroll" then
|
|
||||||
local directions = {
|
|
||||||
[ -1 ] = 'scrollUp',
|
|
||||||
[ 1 ] = 'scrollDown'
|
|
||||||
}
|
|
||||||
return directions[code]
|
|
||||||
|
|
||||||
elseif event == 'paste' then
|
|
||||||
self.combo = true
|
|
||||||
return event
|
|
||||||
|
|
||||||
elseif event == 'mouse_drag' then
|
|
||||||
return event
|
|
||||||
end
|
end
|
||||||
|
elseif not code or not modifiers[code] then
|
||||||
|
table.insert(result, ch)
|
||||||
|
end
|
||||||
|
|
||||||
|
return table.concat(result, '-')
|
||||||
|
end
|
||||||
|
|
||||||
|
function input:reset()
|
||||||
|
self.pressed = { }
|
||||||
|
self.fired = nil
|
||||||
|
|
||||||
|
self.timer = nil
|
||||||
|
self.mch = nil
|
||||||
|
self.mfired = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function input:translate(event, code, p1, p2)
|
||||||
|
if event == 'key' then
|
||||||
|
if p1 then -- key is held down
|
||||||
|
if not modifiers[code] then
|
||||||
|
self.fired = true
|
||||||
|
return input:toCode(keys.getName(code), code)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.pressed[code] = true
|
||||||
|
if self:modifierPressed() and not modifiers[code] or code == 57 then
|
||||||
|
self.fired = true
|
||||||
|
return input:toCode(keys.getName(code), code)
|
||||||
|
else
|
||||||
|
self.fired = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif event == 'char' then
|
||||||
|
if not self:modifierPressed() then
|
||||||
|
self.fired = true
|
||||||
|
return input:toCode(code)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif event == 'key_up' then
|
||||||
|
if not self.fired then
|
||||||
|
if self.pressed[code] then
|
||||||
|
self.fired = true
|
||||||
|
local ch = input:toCode(keys.getName(code), code)
|
||||||
|
self.pressed[code] = nil
|
||||||
|
return ch
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.pressed[code] = nil
|
||||||
|
|
||||||
|
elseif event == 'paste' then
|
||||||
|
self.pressed[keys.leftCtrl] = nil
|
||||||
|
self.pressed[keys.rightCtrl] = nil
|
||||||
|
self.fired = true
|
||||||
|
if clipboard then
|
||||||
|
return 'paste'
|
||||||
|
end
|
||||||
|
return input:toCode('paste', 255)
|
||||||
|
|
||||||
|
elseif event == 'mouse_click' then
|
||||||
|
local buttons = { 'mouse_click', 'mouse_rightclick' }
|
||||||
|
self.mch = buttons[code]
|
||||||
|
self.mfired = nil
|
||||||
|
|
||||||
|
elseif event == 'mouse_drag' then
|
||||||
|
self.mfired = true
|
||||||
|
self.fired = true
|
||||||
|
return input:toCode('mouse_drag', 255)
|
||||||
|
|
||||||
|
elseif event == 'mouse_up' then
|
||||||
|
if not self.mfired then
|
||||||
|
local clock = os.clock()
|
||||||
|
if self.timer and
|
||||||
|
p1 == self.x and p2 == self.y and
|
||||||
|
(clock - self.timer < .5) then
|
||||||
|
|
||||||
|
self.mch = 'mouse_doubleclick'
|
||||||
|
self.timer = nil
|
||||||
|
else
|
||||||
|
self.timer = os.clock()
|
||||||
|
self.x = p1
|
||||||
|
self.y = p2
|
||||||
|
end
|
||||||
|
self.mfired = input:toCode(self.mch, 255)
|
||||||
|
else
|
||||||
|
self.mch = 'mouse_up'
|
||||||
|
self.mfired = input:toCode(self.mch, 255)
|
||||||
|
end
|
||||||
|
self.fired = true
|
||||||
|
return self.mfired
|
||||||
|
|
||||||
|
elseif event == "mouse_scroll" then
|
||||||
|
local directions = {
|
||||||
|
[ -1 ] = 'scrollUp',
|
||||||
|
[ 1 ] = 'scrollDown'
|
||||||
|
}
|
||||||
|
self.fired = true
|
||||||
|
return input:toCode(directions[code], 255)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
load(sPath)
|
||||||
|
term.setCursorBlink(true)
|
||||||
|
redraw()
|
||||||
|
|
||||||
while bRunning do
|
while bRunning do
|
||||||
local sEvent, param, param2, param3 = os.pullEventRaw()
|
local sEvent, param, param2, param3 = os.pullEventRaw()
|
||||||
local action
|
local action
|
||||||
|
|
||||||
if sEvent == 'terminate' then
|
if sEvent == 'terminate' then
|
||||||
action = 'exit'
|
action = 'exit'
|
||||||
elseif sEvent == "mouse_click" or sEvent == 'mouse_drag' then
|
elseif sEvent == 'multishell_focus' then -- opus only event
|
||||||
|
input:reset()
|
||||||
|
elseif sEvent == "mouse_click" or sEvent == 'mouse_drag' or sEvent == 'mouse_up' then
|
||||||
|
local ch = input:translate(sEvent, param, param2, param3)
|
||||||
if param3 < h or sEvent == 'mouse_drag' then
|
if param3 < h or sEvent == 'mouse_drag' then
|
||||||
local ch = keyboard:translate(sEvent, param)
|
|
||||||
if ch then
|
if ch then
|
||||||
action = keyMapping[ch]
|
action = keyMapping[ch]
|
||||||
param = param2 + scrollX
|
param = param2 + scrollX
|
||||||
@@ -1231,9 +1252,14 @@ while bRunning do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local ch = keyboard:translate(sEvent, param)
|
local ch = input:translate(sEvent, param, param2)
|
||||||
if ch then
|
if ch then
|
||||||
action = keyMapping[ch]
|
if #ch == 1 then
|
||||||
|
action = keyMapping.char
|
||||||
|
param = ch
|
||||||
|
else
|
||||||
|
action = keyMapping[ch]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1247,7 +1273,7 @@ while bRunning do
|
|||||||
|
|
||||||
actions[action](param, param2)
|
actions[action](param, param2)
|
||||||
if action ~= 'menu' then
|
if action ~= 'menu' then
|
||||||
keyboard.lastAction = action
|
lastAction = action
|
||||||
end
|
end
|
||||||
|
|
||||||
if x ~= lastPos.x or y ~= lastPos.y then
|
if x ~= lastPos.x or y ~= lastPos.y then
|
||||||
|
|||||||
376
apps/levelEmitter.lua
Normal file
376
apps/levelEmitter.lua
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
_G.requireInjector()
|
||||||
|
|
||||||
|
local InventoryAdapter = require('inventoryAdapter')
|
||||||
|
local Config = require('config')
|
||||||
|
local Event = require('event')
|
||||||
|
local itemDB = require('itemDB')
|
||||||
|
local UI = require('ui')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local rs = _G.rs
|
||||||
|
|
||||||
|
local RESOURCE_FILE = 'usr/config/levelEmitter.db'
|
||||||
|
|
||||||
|
multishell.setTitle(multishell.getCurrent(), 'Level Emitter')
|
||||||
|
|
||||||
|
local config = {
|
||||||
|
inventorySide = 'bottom',
|
||||||
|
}
|
||||||
|
Config.loadWithCheck('levelEmitter', config)
|
||||||
|
|
||||||
|
local inventoryAdapter = InventoryAdapter.wrap({ wrapSide = config.inventorySide })
|
||||||
|
if not inventoryAdapter then
|
||||||
|
error('No inventory found')
|
||||||
|
end
|
||||||
|
|
||||||
|
local resources
|
||||||
|
|
||||||
|
local function getItem(items, inItem, ignoreDamage, ignoreNbtHash)
|
||||||
|
for _,item in pairs(items) do
|
||||||
|
if item.name == inItem.name and
|
||||||
|
(ignoreDamage or item.damage == inItem.damage) and
|
||||||
|
(ignoreNbtHash or item.nbtHash == inItem.nbtHash) then
|
||||||
|
return item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function uniqueKey(item)
|
||||||
|
return table.concat({ item.name, item.damage, item.nbtHash }, ':')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mergeResources(t)
|
||||||
|
for _,v in pairs(resources) do
|
||||||
|
local item = getItem(t, v)
|
||||||
|
if item then
|
||||||
|
Util.merge(item, v)
|
||||||
|
else
|
||||||
|
item = Util.shallowCopy(v)
|
||||||
|
item.count = 0
|
||||||
|
table.insert(t, item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,v in pairs(t) do
|
||||||
|
if not v.displayName then
|
||||||
|
v.displayName = itemDB:getName(v)
|
||||||
|
end
|
||||||
|
v.lname = v.displayName:lower()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getItemWithQty(items, res, ignoreDamage, ignoreNbtHash)
|
||||||
|
local item = getItem(items, res, ignoreDamage, ignoreNbtHash)
|
||||||
|
|
||||||
|
if item and (ignoreDamage or ignoreNbtHash) then
|
||||||
|
local count = 0
|
||||||
|
|
||||||
|
for _,v in pairs(items) do
|
||||||
|
if item.name == v.name and
|
||||||
|
(ignoreDamage or item.damage == v.damage) and
|
||||||
|
(ignoreNbtHash or item.nbtHash == v.nbtHash) then
|
||||||
|
count = count + v.count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
item.count = count
|
||||||
|
end
|
||||||
|
|
||||||
|
return item
|
||||||
|
end
|
||||||
|
|
||||||
|
local function loadResources()
|
||||||
|
resources = Util.readTable(RESOURCE_FILE) or { }
|
||||||
|
for k,v in pairs(resources) do
|
||||||
|
Util.merge(v, itemDB:splitKey(k))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function saveResources()
|
||||||
|
local t = { }
|
||||||
|
|
||||||
|
for k,v in pairs(resources) do
|
||||||
|
v = Util.shallowCopy(v)
|
||||||
|
local keys = Util.transpose({ 'limit', 'low', 'ignoreDamage', 'ignoreNbtHash' })
|
||||||
|
|
||||||
|
for _,key in pairs(Util.keys(v)) do
|
||||||
|
if not keys[key] then
|
||||||
|
v[key] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not Util.empty(v) then
|
||||||
|
t[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Util.writeTable(RESOURCE_FILE, t)
|
||||||
|
end
|
||||||
|
|
||||||
|
local itemPage = UI.Page {
|
||||||
|
titleBar = UI.TitleBar {
|
||||||
|
title = 'Limit Resource',
|
||||||
|
previousPage = true,
|
||||||
|
event = 'form_cancel',
|
||||||
|
},
|
||||||
|
form = UI.Form {
|
||||||
|
x = 1, y = 2, height = 10, ex = -1,
|
||||||
|
[1] = UI.TextEntry {
|
||||||
|
width = 7,
|
||||||
|
formLabel = 'Min', formKey = 'low', help = 'Output a signal if below'
|
||||||
|
},
|
||||||
|
[2] = UI.TextEntry {
|
||||||
|
width = 7,
|
||||||
|
formLabel = 'Max', formKey = 'limit', help = 'Output a signal if above'
|
||||||
|
},
|
||||||
|
[4] = UI.Chooser {
|
||||||
|
width = 7,
|
||||||
|
formLabel = 'Ignore Dmg', formKey = 'ignoreDamage',
|
||||||
|
nochoice = 'No',
|
||||||
|
choices = {
|
||||||
|
{ name = 'Yes', value = true },
|
||||||
|
{ name = 'No', value = false },
|
||||||
|
},
|
||||||
|
help = 'Ignore damage of item'
|
||||||
|
},
|
||||||
|
[5] = UI.Chooser {
|
||||||
|
width = 7,
|
||||||
|
formLabel = 'Ignore NBT', formKey = 'ignoreNbtHash',
|
||||||
|
nochoice = 'No',
|
||||||
|
choices = {
|
||||||
|
{ name = 'Yes', value = true },
|
||||||
|
{ name = 'No', value = false },
|
||||||
|
},
|
||||||
|
help = 'Ignore NBT of item'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
statusBar = UI.StatusBar { }
|
||||||
|
}
|
||||||
|
|
||||||
|
function itemPage:enable(item)
|
||||||
|
self.item = Util.shallowCopy(item)
|
||||||
|
|
||||||
|
self.form:setValues(item)
|
||||||
|
self.titleBar.title = item.displayName or item.name
|
||||||
|
|
||||||
|
UI.Page.enable(self)
|
||||||
|
self:focusFirst()
|
||||||
|
end
|
||||||
|
|
||||||
|
function itemPage:eventHandler(event)
|
||||||
|
if event.type == 'form_cancel' then
|
||||||
|
UI:setPreviousPage()
|
||||||
|
|
||||||
|
elseif event.type == 'focus_change' then
|
||||||
|
self.statusBar:setStatus(event.focused.help)
|
||||||
|
self.statusBar:draw()
|
||||||
|
|
||||||
|
elseif event.type == 'form_complete' then
|
||||||
|
local filtered = Util.shallowCopy(self.form.values)
|
||||||
|
|
||||||
|
if filtered.ignoreDamage == true then
|
||||||
|
filtered.damage = 0
|
||||||
|
else
|
||||||
|
filtered.ignoreDamage = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if filtered.ignoreNbtHash == true then
|
||||||
|
filtered.nbtHash = nil
|
||||||
|
else
|
||||||
|
filtered.ignoreNbtHash = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local originalKey = uniqueKey(self.item)
|
||||||
|
resources[originalKey] = nil
|
||||||
|
|
||||||
|
filtered.low = tonumber(filtered.low)
|
||||||
|
filtered.limit = tonumber(filtered.limit)
|
||||||
|
if filtered.limit or filtered.low then
|
||||||
|
resources[uniqueKey(filtered)] = filtered
|
||||||
|
else
|
||||||
|
resources[uniqueKey(filtered)] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
saveResources()
|
||||||
|
|
||||||
|
UI:setPreviousPage()
|
||||||
|
|
||||||
|
else
|
||||||
|
return UI.Page.eventHandler(self, event)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local listingPage = UI.Page {
|
||||||
|
menuBar = UI.MenuBar {
|
||||||
|
buttons = {
|
||||||
|
{ text = 'Forget', event = 'forget' },
|
||||||
|
{ text = 'Refresh', event = 'refresh', x = -9 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid = UI.Grid {
|
||||||
|
y = 2, height = UI.term.height - 2,
|
||||||
|
columns = {
|
||||||
|
{ heading = 'Name', key = 'displayName' , width = 22 },
|
||||||
|
{ heading = 'Qty', key = 'count' , width = 5 },
|
||||||
|
{ heading = 'Min', key = 'limit' , width = 4 },
|
||||||
|
{ heading = 'Max', key = 'low' , width = 4 },
|
||||||
|
},
|
||||||
|
sortColumn = 'displayName',
|
||||||
|
},
|
||||||
|
statusBar = UI.StatusBar {
|
||||||
|
filterText = UI.Text {
|
||||||
|
x = 2,
|
||||||
|
value = 'Filter',
|
||||||
|
},
|
||||||
|
filter = UI.TextEntry {
|
||||||
|
x = 9, ex = -5,
|
||||||
|
limit = 50,
|
||||||
|
backgroundColor = colors.gray,
|
||||||
|
backgroundFocusColor = colors.gray,
|
||||||
|
},
|
||||||
|
display = UI.Button {
|
||||||
|
x = -3,
|
||||||
|
event = 'toggle_display',
|
||||||
|
value = 0,
|
||||||
|
text = 'A',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
accelerators = {
|
||||||
|
r = 'refresh',
|
||||||
|
q = 'quit',
|
||||||
|
},
|
||||||
|
displayMode = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
function listingPage.grid:getDisplayValues(row)
|
||||||
|
row = Util.shallowCopy(row)
|
||||||
|
row.count = Util.toBytes(row.count)
|
||||||
|
if row.low then
|
||||||
|
row.low = Util.toBytes(row.low)
|
||||||
|
end
|
||||||
|
if row.limit then
|
||||||
|
row.limit = Util.toBytes(row.limit)
|
||||||
|
end
|
||||||
|
return row
|
||||||
|
end
|
||||||
|
|
||||||
|
function listingPage:eventHandler(event)
|
||||||
|
if event.type == 'quit' then
|
||||||
|
UI:exitPullEvents()
|
||||||
|
|
||||||
|
elseif event.type == 'grid_select' then
|
||||||
|
local selected = event.selected
|
||||||
|
UI:setPage('item', selected)
|
||||||
|
|
||||||
|
elseif event.type == 'refresh' then
|
||||||
|
self:refresh()
|
||||||
|
self.grid:draw()
|
||||||
|
self.statusBar.filter:focus()
|
||||||
|
|
||||||
|
elseif event.type == 'toggle_display' then
|
||||||
|
local values = {
|
||||||
|
[0] = 'A',
|
||||||
|
[1] = 'I',
|
||||||
|
[2] = 'C',
|
||||||
|
}
|
||||||
|
|
||||||
|
event.button.value = (event.button.value + 1) % 3
|
||||||
|
self.displayMode = event.button.value
|
||||||
|
event.button.text = values[event.button.value]
|
||||||
|
event.button:draw()
|
||||||
|
self:applyFilter()
|
||||||
|
self.grid:draw()
|
||||||
|
|
||||||
|
elseif event.type == 'forget' then
|
||||||
|
local item = self.grid:getSelected()
|
||||||
|
if item then
|
||||||
|
local key = uniqueKey(item)
|
||||||
|
|
||||||
|
if resources[key] then
|
||||||
|
resources[key] = nil
|
||||||
|
saveResources()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.statusBar:timedStatus('Forgot: ' .. item.name, 3)
|
||||||
|
self:refresh()
|
||||||
|
self.grid:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif event.type == 'text_change' then
|
||||||
|
self.filter = event.text
|
||||||
|
if #self.filter == 0 then
|
||||||
|
self.filter = nil
|
||||||
|
end
|
||||||
|
self:applyFilter()
|
||||||
|
self.grid:draw()
|
||||||
|
self.statusBar.filter:focus()
|
||||||
|
|
||||||
|
else
|
||||||
|
UI.Page.eventHandler(self, event)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function listingPage:enable()
|
||||||
|
self:refresh()
|
||||||
|
self:setFocus(self.statusBar.filter)
|
||||||
|
UI.Page.enable(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function listingPage:refresh()
|
||||||
|
self.allItems = inventoryAdapter:listItems()
|
||||||
|
mergeResources(self.allItems)
|
||||||
|
self:applyFilter()
|
||||||
|
end
|
||||||
|
|
||||||
|
function listingPage:applyFilter()
|
||||||
|
local filter = self.filter
|
||||||
|
local displayMode = self.displayMode
|
||||||
|
local t = self.allItems
|
||||||
|
|
||||||
|
if filter or displayMode > 0 then
|
||||||
|
t = { }
|
||||||
|
if filter then
|
||||||
|
filter = filter:lower()
|
||||||
|
end
|
||||||
|
for _,v in pairs(self.allItems) do
|
||||||
|
if not filter or string.find(v.lname, filter, 1, true) then
|
||||||
|
if not displayMode or
|
||||||
|
displayMode == 0 or
|
||||||
|
displayMode == 1 and v.count > 0 or
|
||||||
|
displayMode == 2 and v.has_recipe then
|
||||||
|
table.insert(t, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.grid:setValues(t)
|
||||||
|
end
|
||||||
|
|
||||||
|
loadResources()
|
||||||
|
|
||||||
|
UI:setPages({
|
||||||
|
listing = listingPage,
|
||||||
|
item = itemPage,
|
||||||
|
})
|
||||||
|
|
||||||
|
UI:setPage(listingPage)
|
||||||
|
listingPage:setFocus(listingPage.statusBar.filter)
|
||||||
|
|
||||||
|
Event.onInterval(5, function()
|
||||||
|
local items = inventoryAdapter:listItems()
|
||||||
|
|
||||||
|
if items and Util.size(items) > 0 then
|
||||||
|
for _,res in pairs(resources) do
|
||||||
|
local item = getItemWithQty(items, res, res.ignoreDamage, res.ignoreNbtHash)
|
||||||
|
rs.setOutput('bottom', (res.limit and
|
||||||
|
item and item.count > res.limit) or
|
||||||
|
(res.low and
|
||||||
|
(not item or item.count < res.low)) or false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
UI:pullEvents()
|
||||||
@@ -36,6 +36,31 @@ elseif device.monitor then
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[-- ScrollingText --]]--
|
||||||
|
UI.ScrollingText = class(UI.Window)
|
||||||
|
UI.ScrollingText.defaults = {
|
||||||
|
UIElement = 'ScrollingText',
|
||||||
|
backgroundColor = colors.black,
|
||||||
|
buffer = { },
|
||||||
|
}
|
||||||
|
function UI.ScrollingText:appendLine(text)
|
||||||
|
if #self.buffer+1 >= self.height then
|
||||||
|
table.remove(self.buffer, 1)
|
||||||
|
end
|
||||||
|
table.insert(self.buffer, text)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.ScrollingText:clear()
|
||||||
|
self.buffer = { }
|
||||||
|
UI.Window.clear(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.ScrollingText:draw()
|
||||||
|
for k,text in ipairs(self.buffer) do
|
||||||
|
self:write(1, k, Util.widthify(text, self.width), self.backgroundColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
terminal:clear()
|
terminal:clear()
|
||||||
|
|
||||||
function getClient(id)
|
function getClient(id)
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Terminal = require('terminal')
|
local Terminal = require('terminal')
|
||||||
|
|
||||||
|
local shell = _ENV.shell
|
||||||
|
local term = _G.term
|
||||||
|
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
local mon = device[table.remove(args, 1) or 'monitor']
|
local mon = _G.device[table.remove(args, 1) or 'monitor']
|
||||||
if not mon then
|
if not mon then
|
||||||
error('mirror: Invalid device')
|
error('mirror: Invalid device')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local Logger = require('logger')
|
local Logger = require('logger')
|
||||||
local Socket = require('socket')
|
local Socket = require('socket')
|
||||||
local Terminal = require('terminal')
|
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
|
||||||
Logger.setScreenLogging()
|
Logger.setScreenLogging()
|
||||||
|
|
||||||
local remoteId
|
local remoteId
|
||||||
@@ -14,7 +16,7 @@ if #args == 1 then
|
|||||||
remoteId = tonumber(args[1])
|
remoteId = tonumber(args[1])
|
||||||
else
|
else
|
||||||
print('Enter host ID')
|
print('Enter host ID')
|
||||||
remoteId = tonumber(read())
|
remoteId = tonumber(_G.read())
|
||||||
end
|
end
|
||||||
|
|
||||||
if not remoteId then
|
if not remoteId then
|
||||||
@@ -70,7 +72,7 @@ while true do
|
|||||||
while true do
|
while true do
|
||||||
local e = Event.pullEvent()
|
local e = Event.pullEvent()
|
||||||
if e[1] == 'terminate' then
|
if e[1] == 'terminate' then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
if not socket.connected then
|
if not socket.connected then
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local Logger = require('logger')
|
local Logger = require('logger')
|
||||||
local Socket = require('socket')
|
local Socket = require('socket')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
local term = _G.term
|
||||||
|
|
||||||
Logger.setScreenLogging()
|
Logger.setScreenLogging()
|
||||||
|
|
||||||
local mon = term.current()
|
local mon = term.current()
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
if args[1] then
|
if args[1] then
|
||||||
mon = device[args[1]]
|
mon = _G.device[args[1]]
|
||||||
end
|
end
|
||||||
|
|
||||||
if not mon then
|
if not mon then
|
||||||
@@ -36,13 +39,6 @@ while true do
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- ensure socket is connected
|
|
||||||
Event.onInterval(3, function(h)
|
|
||||||
if not socket:ping() then
|
|
||||||
Event.off(h)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
Event.pullEvent()
|
Event.pullEvent()
|
||||||
if not socket.connected then
|
if not socket.connected then
|
||||||
|
|||||||
@@ -1,23 +1,27 @@
|
|||||||
require = requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
local device = _G.device
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'Music')
|
multishell.setTitle(multishell.getCurrent(), 'Music')
|
||||||
|
|
||||||
|
if not turtle then
|
||||||
|
error('This program can only be run on a turtle')
|
||||||
|
end
|
||||||
|
|
||||||
local radio = device.drive or error('No drive attached')
|
local radio = device.drive or error('No drive attached')
|
||||||
if radio.side ~= 'top' and radio.side ~= 'bottom' then
|
if radio.side ~= 'top' and radio.side ~= 'bottom' then
|
||||||
error('Disk drive must be above or below turtle')
|
error('Disk drive must be above or below turtle')
|
||||||
end
|
end
|
||||||
|
|
||||||
if not turtle then
|
|
||||||
error('This program can only be run on a turtle')
|
|
||||||
end
|
|
||||||
|
|
||||||
UI:configure('Music', ...)
|
UI:configure('Music', ...)
|
||||||
|
|
||||||
local monitor = UI.term
|
|
||||||
|
|
||||||
UI.Button.defaults.backgroundFocusColor = colors.gray
|
UI.Button.defaults.backgroundFocusColor = colors.gray
|
||||||
|
|
||||||
local page = UI.Page({
|
local page = UI.Page({
|
||||||
@@ -146,7 +150,7 @@ function page:eventHandler(event)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function page:setVolume(volume, displayOnly)
|
function page:setVolume(volume)
|
||||||
volume = math.min(volume, 15)
|
volume = math.min(volume, 15)
|
||||||
volume = math.max(volume, 1)
|
volume = math.max(volume, 1)
|
||||||
self.volume = volume
|
self.volume = volume
|
||||||
@@ -248,9 +252,9 @@ page:setVolume(page.volume, true)
|
|||||||
|
|
||||||
UI:setPage(page)
|
UI:setPage(page)
|
||||||
|
|
||||||
turtle.status = 'Jamming'
|
turtle.setStatus('Jamming')
|
||||||
UI:pullEvents()
|
UI:pullEvents()
|
||||||
turtle.status = 'idle'
|
turtle.setStatus('idle')
|
||||||
page:play(false)
|
page:play(false)
|
||||||
|
|
||||||
UI.term:reset()
|
UI.term:reset()
|
||||||
|
|||||||
24
apps/mwm.lua
24
apps/mwm.lua
@@ -1,9 +1,17 @@
|
|||||||
local injector = requireInjector or load(http.get('https://raw.githubusercontent.com/kepler155c/opus/master/sys/apis/injector.lua').readAll())()
|
local injector = _G.requireInjector or load(http.get('https://raw.githubusercontent.com/kepler155c/opus/develop/sys/apis/injector.lua').readAll())()
|
||||||
injector(getfenv(1))
|
injector()
|
||||||
|
|
||||||
local Canvas = require('ui.canvas')
|
local Canvas = require('ui.canvas')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
local os = _G.os
|
||||||
|
local peripheral = _G.peripheral
|
||||||
|
local printError = _G.printError
|
||||||
|
local shell = _ENV.shell
|
||||||
|
local term = _G.term
|
||||||
|
local window = _G.window
|
||||||
|
|
||||||
local function syntax()
|
local function syntax()
|
||||||
printError('Syntax:')
|
printError('Syntax:')
|
||||||
error('mwm sessionName [monitor]')
|
error('mwm sessionName [monitor]')
|
||||||
@@ -14,11 +22,11 @@ local UID = 0
|
|||||||
local multishell = { }
|
local multishell = { }
|
||||||
local processes = { }
|
local processes = { }
|
||||||
local parentTerm = term.current()
|
local parentTerm = term.current()
|
||||||
local sessionFile = args[1] or syntax()
|
local sessionFile = args[1] or 'usr/config/mwm'
|
||||||
local running
|
local running
|
||||||
local monitor
|
local monitor
|
||||||
|
|
||||||
local defaultEnv = Util.shallowCopy(getfenv(1))
|
local defaultEnv = Util.shallowCopy(_ENV)
|
||||||
defaultEnv.multishell = multishell
|
defaultEnv.multishell = multishell
|
||||||
|
|
||||||
if args[2] then
|
if args[2] then
|
||||||
@@ -356,7 +364,7 @@ function multishell.removeProcess(process)
|
|||||||
redraw()
|
redraw()
|
||||||
end
|
end
|
||||||
|
|
||||||
function multishell.saveSession(sessionFile)
|
function multishell.saveSession(filename)
|
||||||
local t = { }
|
local t = { }
|
||||||
for _,process in pairs(processes) do
|
for _,process in pairs(processes) do
|
||||||
if process.path and not process.isShell then
|
if process.path and not process.isShell then
|
||||||
@@ -370,11 +378,11 @@ function multishell.saveSession(sessionFile)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Util.writeTable(sessionFile, t)
|
Util.writeTable(filename, t)
|
||||||
end
|
end
|
||||||
|
|
||||||
function multishell.loadSession(sessionFile)
|
function multishell.loadSession(filename)
|
||||||
local config = Util.readTable(sessionFile)
|
local config = Util.readTable(filename)
|
||||||
if config then
|
if config then
|
||||||
for _,v in pairs(config) do
|
for _,v in pairs(config) do
|
||||||
multishell.openTab(v)
|
multishell.openTab(v)
|
||||||
|
|||||||
113
apps/pickup.lua
113
apps/pickup.lua
@@ -1,12 +1,17 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local GPS = require('gps')
|
|
||||||
local ChestAdapter = require('chestAdapter18')
|
local ChestAdapter = require('chestAdapter18')
|
||||||
local Point = require('point')
|
local Point = require('point')
|
||||||
local Socket = require('socket')
|
local Socket = require('socket')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local device = _G.device
|
||||||
|
local os = _G.os
|
||||||
|
local peripheral = _G.peripheral
|
||||||
|
local printError = _G.printError
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
if not device.wireless_modem then
|
if not device.wireless_modem then
|
||||||
error('Modem is required')
|
error('Modem is required')
|
||||||
end
|
end
|
||||||
@@ -35,7 +40,7 @@ local fuel = {
|
|||||||
|
|
||||||
local slots
|
local slots
|
||||||
|
|
||||||
turtle.setMoveCallback(function(action, pt)
|
turtle.setMoveCallback(function()
|
||||||
if slots then
|
if slots then
|
||||||
for _,slot in pairs(slots) do
|
for _,slot in pairs(slots) do
|
||||||
if turtle.getItemCount(slot.index) ~= slot.qty then
|
if turtle.getItemCount(slot.index) ~= slot.qty then
|
||||||
@@ -46,10 +51,38 @@ turtle.setMoveCallback(function(action, pt)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function refuel()
|
local function gotoPoint(pt, doDetect)
|
||||||
|
slots = turtle.getInventory()
|
||||||
|
while not turtle.pathfind(pt, { blocks = blocks }) do
|
||||||
|
if turtle.isAborted() then
|
||||||
|
error('aborted')
|
||||||
|
end
|
||||||
|
turtle.setStatus('blocked')
|
||||||
|
os.sleep(5)
|
||||||
|
end
|
||||||
|
|
||||||
|
if doDetect and not turtle.detectDown() then
|
||||||
|
printError('Missing target')
|
||||||
|
Event.exitPullEvents()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function dropOff(pt)
|
||||||
|
if turtle.selectSlotWithItems() then
|
||||||
|
gotoPoint(pt, true)
|
||||||
|
turtle.emptyInventory(turtle.dropDown)
|
||||||
|
if pt == locations.dropPt then
|
||||||
|
print('refreshing items')
|
||||||
|
local chestAdapter = ChestAdapter()
|
||||||
|
items = chestAdapter:refresh()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function refuel()
|
||||||
if turtle.getFuelLevel() < 5000 and locations.dropPt then
|
if turtle.getFuelLevel() < 5000 and locations.dropPt then
|
||||||
print('refueling')
|
print('refueling')
|
||||||
turtle.status = 'refueling'
|
turtle.setStatus('refueling')
|
||||||
gotoPoint(locations.dropPt, true)
|
gotoPoint(locations.dropPt, true)
|
||||||
dropOff(locations.dropPt)
|
dropOff(locations.dropPt)
|
||||||
local chestAdapter = ChestAdapter({
|
local chestAdapter = ChestAdapter({
|
||||||
@@ -66,8 +99,8 @@ function refuel()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function pickUp(pt)
|
local function pickUp(pt)
|
||||||
turtle.status = 'picking up'
|
turtle.setStatus('picking up')
|
||||||
gotoPoint(pt, true)
|
gotoPoint(pt, true)
|
||||||
while true do
|
while true do
|
||||||
if not turtle.selectOpenSlot() then
|
if not turtle.selectOpenSlot() then
|
||||||
@@ -81,41 +114,13 @@ function pickUp(pt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function dropOff(pt)
|
local function checkCell(pt)
|
||||||
if turtle.selectSlotWithItems() then
|
|
||||||
gotoPoint(pt, true)
|
|
||||||
turtle.emptyInventory(turtle.dropDown)
|
|
||||||
if pt == locations.dropPt then
|
|
||||||
print('refreshing items')
|
|
||||||
chestAdapter = ChestAdapter()
|
|
||||||
items = chestAdapter:refresh()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function gotoPoint(pt, doDetect)
|
|
||||||
slots = turtle.getInventory()
|
|
||||||
while not turtle.pathfind(pt, { blocks = blocks }) do
|
|
||||||
if turtle.abort then
|
|
||||||
error('aborted')
|
|
||||||
end
|
|
||||||
turtle.status = 'blocked'
|
|
||||||
os.sleep(5)
|
|
||||||
end
|
|
||||||
|
|
||||||
if doDetect and not turtle.detectDown() then
|
|
||||||
printError('Missing target')
|
|
||||||
Event.exitPullEvents()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function checkCell(pt)
|
|
||||||
if not turtle.selectOpenSlot() then
|
if not turtle.selectOpenSlot() then
|
||||||
dropOff(locations.dropPt)
|
dropOff(locations.dropPt)
|
||||||
end
|
end
|
||||||
|
|
||||||
print('checking cell')
|
print('checking cell')
|
||||||
turtle.status = 'recharging'
|
turtle.setStatus('recharging')
|
||||||
gotoPoint(pt, true)
|
gotoPoint(pt, true)
|
||||||
local c = peripheral.wrap('bottom')
|
local c = peripheral.wrap('bottom')
|
||||||
local energy = c.getMaxEnergyStored() -
|
local energy = c.getMaxEnergyStored() -
|
||||||
@@ -136,9 +141,9 @@ function checkCell(pt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function fluid(points)
|
local function fluid(points)
|
||||||
print('checking fluid')
|
print('checking fluid')
|
||||||
turtle.status = 'fluiding'
|
turtle.setStatus('fluiding')
|
||||||
gotoPoint(points.source, true)
|
gotoPoint(points.source, true)
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
turtle.digDown()
|
turtle.digDown()
|
||||||
@@ -152,10 +157,10 @@ function fluid(points)
|
|||||||
turtle.placeDown()
|
turtle.placeDown()
|
||||||
end
|
end
|
||||||
|
|
||||||
function refill(entry)
|
local function refill(entry)
|
||||||
dropOff(locations.dropPt)
|
dropOff(locations.dropPt)
|
||||||
|
|
||||||
turtle.status = 'refilling'
|
turtle.setStatus('refilling')
|
||||||
gotoPoint(locations.dropPt)
|
gotoPoint(locations.dropPt)
|
||||||
local chestAdapter = ChestAdapter()
|
local chestAdapter = ChestAdapter()
|
||||||
for _,item in pairs(entry.items) do
|
for _,item in pairs(entry.items) do
|
||||||
@@ -169,21 +174,6 @@ function refill(entry)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function oldRefill(points)
|
|
||||||
gotoPoint(points.source)
|
|
||||||
repeat until not turtle.suckDown(64)
|
|
||||||
if points.target then
|
|
||||||
dropOff(points.target)
|
|
||||||
end
|
|
||||||
if points.targets then
|
|
||||||
for k,target in pairs(points.targets) do
|
|
||||||
dropOff(target)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
dropOff(points.source)
|
|
||||||
dropOff(locations.dropPt)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function makeKey(pt)
|
local function makeKey(pt)
|
||||||
return string.format('%d:%d:%d', pt.x, pt.y, pt.z)
|
return string.format('%d:%d:%d', pt.x, pt.y, pt.z)
|
||||||
end
|
end
|
||||||
@@ -230,8 +220,6 @@ local function pickupHost(socket)
|
|||||||
Util.writeTable('/usr/config/pickup', locations)
|
Util.writeTable('/usr/config/pickup', locations)
|
||||||
socket:write( { type = "response", response = 'added' })
|
socket:write( { type = "response", response = 'added' })
|
||||||
|
|
||||||
elseif data.type == 'fluid' then
|
|
||||||
|
|
||||||
elseif data.type == 'clear' then
|
elseif data.type == 'clear' then
|
||||||
local key = makeKey(data.point)
|
local key = makeKey(data.point)
|
||||||
locations.refills[key] = nil
|
locations.refills[key] = nil
|
||||||
@@ -264,7 +252,7 @@ local function eachEntry(t, fn)
|
|||||||
local keys = Util.keys(t)
|
local keys = Util.keys(t)
|
||||||
for _,key in pairs(keys) do
|
for _,key in pairs(keys) do
|
||||||
if t[key] then
|
if t[key] then
|
||||||
if turtle.abort then
|
if turtle.isAborted() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
fn(t[key])
|
fn(t[key])
|
||||||
@@ -283,7 +271,7 @@ local function eachClosestEntry(t, fn)
|
|||||||
|
|
||||||
while not Util.empty(points) do
|
while not Util.empty(points) do
|
||||||
local closest = Point.closest(turtle.point, points)
|
local closest = Point.closest(turtle.point, points)
|
||||||
if turtle.abort then
|
if turtle.isAborted() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if t[closest.key] then
|
if t[closest.key] then
|
||||||
@@ -299,7 +287,6 @@ local function eachClosestEntry(t, fn)
|
|||||||
end
|
end
|
||||||
|
|
||||||
Event.addRoutine(function()
|
Event.addRoutine(function()
|
||||||
|
|
||||||
if not turtle.enableGPS() then
|
if not turtle.enableGPS() then
|
||||||
error('turtle: No GPS found')
|
error('turtle: No GPS found')
|
||||||
end
|
end
|
||||||
@@ -318,8 +305,8 @@ Event.addRoutine(function()
|
|||||||
eachEntry(locations.cells, checkCell)
|
eachEntry(locations.cells, checkCell)
|
||||||
end
|
end
|
||||||
print('sleeping')
|
print('sleeping')
|
||||||
turtle.status = 'sleeping'
|
turtle.setStatus('sleeping')
|
||||||
if turtle.abort then
|
if turtle.isAborted() then
|
||||||
printError('aborted')
|
printError('aborted')
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -83,7 +83,10 @@ local function loadAPI(url, env)
|
|||||||
apiEnv.shell = nil
|
apiEnv.shell = nil
|
||||||
apiEnv.multishell = nil
|
apiEnv.multishell = nil
|
||||||
setmetatable(apiEnv, { __index = _G })
|
setmetatable(apiEnv, { __index = _G })
|
||||||
local fn = Util.loadUrl(url, apiEnv)
|
local fn, m = Util.loadUrl(url, apiEnv)
|
||||||
|
if not fn then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
fn()
|
fn()
|
||||||
return apiEnv
|
return apiEnv
|
||||||
end
|
end
|
||||||
@@ -91,7 +94,10 @@ end
|
|||||||
bbpack = loadAPI('http://pastebin.com/raw/PdrJjb5S', getfenv(1))
|
bbpack = loadAPI('http://pastebin.com/raw/PdrJjb5S', getfenv(1))
|
||||||
GIF = loadAPI('http://pastebin.com/raw/5uk9uRjC', getfenv(1))
|
GIF = loadAPI('http://pastebin.com/raw/5uk9uRjC', getfenv(1))
|
||||||
|
|
||||||
Util.runUrl(getfenv(1), 'http://pastebin.com/raw/cUYTGbpb', 'get', 'CnLzL5fg')
|
local s, m = Util.runUrl(getfenv(1), 'http://pastebin.com/raw/cUYTGbpb', 'get', 'CnLzL5fg')
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
-- 'Y0eLUPtr')
|
-- 'Y0eLUPtr')
|
||||||
-- CnLzL5fg
|
-- CnLzL5fg
|
||||||
local function snooze()
|
local function snooze()
|
||||||
@@ -141,7 +147,7 @@ end
|
|||||||
|
|
||||||
local tabId = multishell.getCurrent()
|
local tabId = multishell.getCurrent()
|
||||||
|
|
||||||
multishell.addHotkey(25, function()
|
multishell.addHotkey('control-p', function()
|
||||||
os.queueEvent('recorder_stop')
|
os.queueEvent('recorder_stop')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -179,7 +185,7 @@ while true do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
multishell.removeHotkey(25)
|
multishell.removeHotkey('control-p')
|
||||||
|
|
||||||
for k,fn in pairs(oldTerm) do
|
for k,fn in pairs(oldTerm) do
|
||||||
multishell.term[k] = fn
|
multishell.term[k] = fn
|
||||||
|
|||||||
288
apps/shapes.lua
288
apps/shapes.lua
@@ -1,283 +1,47 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local GPS = require('gps')
|
local GPS = require('gps')
|
||||||
local Socket = require('socket')
|
local Socket = require('socket')
|
||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local textutils = _G.textutils
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'Shapes')
|
multishell.setTitle(multishell.getCurrent(), 'Shapes')
|
||||||
|
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
local turtleId = args[1] or error('Supply turtle ID')
|
local turtleId = args[1] or error('Supply turtle ID')
|
||||||
turtleId = tonumber(turtleId)
|
turtleId = tonumber(turtleId)
|
||||||
|
|
||||||
local script = [[
|
|
||||||
|
|
||||||
requireInjector(getfenv(1))
|
|
||||||
|
|
||||||
local GPS = require('gps')
|
|
||||||
local ChestAdapter = require('chestAdapter18')
|
|
||||||
local Point = require('point')
|
|
||||||
local Util = require('util')
|
|
||||||
|
|
||||||
local itemAdapter
|
|
||||||
|
|
||||||
function dumpInventory()
|
|
||||||
|
|
||||||
for i = 1, 16 do
|
|
||||||
local qty = turtle.getItemCount(i)
|
|
||||||
if qty > 0 then
|
|
||||||
itemAdapter:insert(i, qty)
|
|
||||||
end
|
|
||||||
if turtle.getItemCount(i) ~= 0 then
|
|
||||||
print('Adapter is full or missing - make space or replace')
|
|
||||||
print('Press enter to continue')
|
|
||||||
read()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
turtle.select(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function refuel()
|
|
||||||
while turtle.getFuelLevel() < 4000 do
|
|
||||||
print('Refueling')
|
|
||||||
turtle.select(1)
|
|
||||||
|
|
||||||
itemAdapter:provide({ name = 'minecraft:coal', damage = 0 }, 64, 1)
|
|
||||||
if turtle.getItemCount(1) == 0 then
|
|
||||||
print('Out of fuel, add fuel to chest/ME system')
|
|
||||||
turtle.status = 'waiting'
|
|
||||||
os.sleep(5)
|
|
||||||
else
|
|
||||||
turtle.refuel(64)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function goto(pt)
|
|
||||||
while not turtle.gotoPoint(pt) do
|
|
||||||
print('stuck')
|
|
||||||
os.sleep(5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pathTo(pt)
|
|
||||||
while not turtle.pathfind(pt) do
|
|
||||||
print('stuck')
|
|
||||||
os.sleep(5)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function resupply()
|
|
||||||
|
|
||||||
if data.suppliesPt then
|
|
||||||
pathTo(data.suppliesPt)
|
|
||||||
|
|
||||||
itemAdapter = ChestAdapter({ direction = 'up', wrapSide = 'bottom' })
|
|
||||||
dumpInventory()
|
|
||||||
refuel()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function makePlane(y)
|
|
||||||
local pt = { x = math.min(data.startPt.x, data.endPt.x),
|
|
||||||
ex = math.max(data.startPt.x, data.endPt.x),
|
|
||||||
z = math.min(data.startPt.z, data.endPt.z),
|
|
||||||
ez = math.max(data.startPt.z, data.endPt.z) }
|
|
||||||
|
|
||||||
local blocks = { }
|
|
||||||
for z = pt.z, pt.ez do
|
|
||||||
for x = pt.x, pt.ex do
|
|
||||||
table.insert(blocks, { x = x, y = y, z = z })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return blocks
|
|
||||||
end
|
|
||||||
|
|
||||||
local function optimizeRoute(plane, ptb)
|
|
||||||
|
|
||||||
local maxDistance = 99999999
|
|
||||||
|
|
||||||
local function getNearestNeighbor(p, pt, threshold)
|
|
||||||
local key, block, heading
|
|
||||||
local moves = maxDistance
|
|
||||||
|
|
||||||
local function getMoves(b, k)
|
|
||||||
local distance = math.abs(pt.x - b.x) + math.abs(pt.z - b.z)
|
|
||||||
|
|
||||||
if distance < moves then
|
|
||||||
-- this operation is expensive - only run if distance is close
|
|
||||||
local c, h = Point.calculateMoves(pt, b, distance)
|
|
||||||
if c < moves then
|
|
||||||
block = b
|
|
||||||
key = k
|
|
||||||
moves = c
|
|
||||||
heading = h
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function blockReady(b)
|
|
||||||
return not b.u
|
|
||||||
end
|
|
||||||
|
|
||||||
local mid = pt.index
|
|
||||||
local forward = mid + 1
|
|
||||||
local backward = mid - 1
|
|
||||||
while forward <= #p or backward > 0 do
|
|
||||||
if forward <= #p then
|
|
||||||
local b = p[forward]
|
|
||||||
if blockReady(b) then
|
|
||||||
getMoves(b, forward)
|
|
||||||
if moves <= threshold then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if moves < maxDistance and math.abs(b.z - pt.z) > moves and pt.index > 0 then
|
|
||||||
forward = #p
|
|
||||||
end
|
|
||||||
end
|
|
||||||
forward = forward + 1
|
|
||||||
end
|
|
||||||
if backward > 0 then
|
|
||||||
local b = p[backward]
|
|
||||||
if blockReady(b) then
|
|
||||||
getMoves(b, backward)
|
|
||||||
if moves <= threshold then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if moves < maxDistance and math.abs(pt.z - b.z) > moves then
|
|
||||||
backward = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
backward = backward - 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
pt.x = block.x
|
|
||||||
pt.z = block.z
|
|
||||||
pt.y = block.y
|
|
||||||
pt.heading = heading
|
|
||||||
pt.index = key
|
|
||||||
block.u = true
|
|
||||||
return block
|
|
||||||
end
|
|
||||||
|
|
||||||
local throttle = Util.throttle()
|
|
||||||
local t = { }
|
|
||||||
ptb.index = 0
|
|
||||||
local threshold = 0
|
|
||||||
for i = 1, #plane do
|
|
||||||
local b = getNearestNeighbor(plane, ptb, threshold)
|
|
||||||
table.insert(t, b)
|
|
||||||
throttle()
|
|
||||||
threshold = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
local function clear()
|
|
||||||
|
|
||||||
local pt = Util.shallowCopy(data.startPt)
|
|
||||||
pt.y = math.min(data.startPt.y, data.endPt.y)
|
|
||||||
pt.heading = 0
|
|
||||||
|
|
||||||
local osy = pt.y
|
|
||||||
local sy = osy + 1
|
|
||||||
local ey = math.max(data.startPt.y, data.endPt.y)
|
|
||||||
local firstPlane = true
|
|
||||||
|
|
||||||
resupply()
|
|
||||||
|
|
||||||
while true do
|
|
||||||
|
|
||||||
if sy > ey then
|
|
||||||
sy = ey
|
|
||||||
end
|
|
||||||
|
|
||||||
local plane = makePlane(sy)
|
|
||||||
plane = optimizeRoute(plane, pt)
|
|
||||||
|
|
||||||
if firstPlane then
|
|
||||||
turtle.pathfind(plane[1])
|
|
||||||
turtle.setPolicy(turtle.policies.digAttack)
|
|
||||||
firstPlane = false
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,b in ipairs(plane) do
|
|
||||||
turtle.gotoPoint(b)
|
|
||||||
if sy < ey then
|
|
||||||
turtle.digUp()
|
|
||||||
end
|
|
||||||
if sy > osy then
|
|
||||||
turtle.digDown()
|
|
||||||
end
|
|
||||||
if turtle.abort then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if turtle.abort then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if sy + 1 >= ey then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
sy = sy + 3
|
|
||||||
end
|
|
||||||
turtle.setPolicy(turtle.policies.none)
|
|
||||||
resupply()
|
|
||||||
end
|
|
||||||
|
|
||||||
turtle.run(function()
|
|
||||||
turtle.status = 'Clearing'
|
|
||||||
|
|
||||||
if turtle.enableGPS() then
|
|
||||||
|
|
||||||
local pt = Util.shallowCopy(turtle.point)
|
|
||||||
local s, m = pcall(clear)
|
|
||||||
pathTo(pt)
|
|
||||||
|
|
||||||
if not s and m then
|
|
||||||
error(m)
|
|
||||||
read()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
]]
|
|
||||||
|
|
||||||
local levelScript = [[
|
local levelScript = [[
|
||||||
|
requireInjector(getfenv(1))
|
||||||
|
|
||||||
requireInjector(getfenv(1))
|
local Util = require('util')
|
||||||
|
|
||||||
local Level = require('turtle.level')
|
local s, m = turtle.run(function()
|
||||||
local Util = require('util')
|
turtle.addFeatures('level')
|
||||||
|
turtle.setStatus('Leveling')
|
||||||
|
|
||||||
local s, m = turtle.run(function()
|
if turtle.enableGPS() then
|
||||||
turtle.status = 'Leveling'
|
local pt = Util.shallowCopy(turtle.point)
|
||||||
|
local s, m = pcall(function()
|
||||||
|
turtle.level(data.startPt, data.endPt, data.firstPt)
|
||||||
|
end)
|
||||||
|
|
||||||
if turtle.enableGPS() then
|
turtle.pathfind(pt)
|
||||||
|
|
||||||
local pt = Util.shallowCopy(turtle.point)
|
if not s and m then
|
||||||
local s, m = pcall(function()
|
error(m)
|
||||||
Level(data.startPt, data.endPt, data.firstPt)
|
end
|
||||||
end)
|
|
||||||
|
|
||||||
turtle.pathfind(pt)
|
|
||||||
|
|
||||||
if not s and m then
|
|
||||||
error(m)
|
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
end
|
end
|
||||||
end)
|
|
||||||
|
|
||||||
if not s then
|
|
||||||
error(m)
|
|
||||||
end
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
|
||||||
local data = Util.readTable('/usr/config/shapes') or { }
|
local data = Util.readTable('/usr/config/shapes') or { }
|
||||||
|
|
||||||
local page = UI.Page {
|
local page = UI.Page {
|
||||||
@@ -295,7 +59,6 @@ local page = UI.Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function page.info:draw()
|
function page.info:draw()
|
||||||
|
|
||||||
local function size(a, b)
|
local function size(a, b)
|
||||||
return (math.abs(a.x - b.x) + 1) *
|
return (math.abs(a.x - b.x) + 1) *
|
||||||
(math.abs(a.y - b.y) + 1) *
|
(math.abs(a.y - b.y) + 1) *
|
||||||
@@ -321,13 +84,12 @@ function page:getPoint()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function page:runFunction(id, script)
|
function page:runFunction(id, script)
|
||||||
|
|
||||||
--Util.writeFile('script.tmp', script)
|
--Util.writeFile('script.tmp', script)
|
||||||
self.notification:info('Connecting')
|
self.notification:info('Connecting')
|
||||||
local fn, msg = loadstring(script, 'script')
|
local fn, msg = loadstring(script, 'script')
|
||||||
if not fn then
|
if not fn then
|
||||||
self.notification:error('Error in script')
|
self.notification:error('Error in script')
|
||||||
-- debug(msg)
|
--debug(msg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -379,7 +141,7 @@ function page:eventHandler(event)
|
|||||||
end
|
end
|
||||||
self.statusBar:setStatus('')
|
self.statusBar:setStatus('')
|
||||||
elseif event.type == 'cancel' then
|
elseif event.type == 'cancel' then
|
||||||
self:runFunction(turtleId, 'turtle.abortAction()')
|
self:runFunction(turtleId, 'turtle.abort(true)')
|
||||||
self.statusBar:setStatus('')
|
self.statusBar:setStatus('')
|
||||||
else
|
else
|
||||||
return UI.Page.eventHandler(self, event)
|
return UI.Page.eventHandler(self, event)
|
||||||
@@ -388,6 +150,4 @@ function page:eventHandler(event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
UI:setPage(page)
|
UI:setPage(page)
|
||||||
|
|
||||||
UI:pullEvents()
|
UI:pullEvents()
|
||||||
UI.term:reset()
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Logger = require('logger')
|
|
||||||
local Pathing = require('turtle.pathfind')
|
local Pathing = require('turtle.pathfind')
|
||||||
local Point = require('point')
|
local Point = require('point')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
if device and device.wireless_modem then
|
local fs = _G.fs
|
||||||
Logger.setWirelessLogging()
|
local read = _G.read
|
||||||
end
|
local os = _G.os
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
local options = {
|
local options = {
|
||||||
@@ -37,25 +37,20 @@ local fortuneBlocks = {
|
|||||||
|
|
||||||
local MIN_FUEL = 7500
|
local MIN_FUEL = 7500
|
||||||
local LOW_FUEL = 1500
|
local LOW_FUEL = 1500
|
||||||
local MAX_FUEL = 100000
|
local MAX_FUEL = turtle.getFuelLimit()
|
||||||
|
|
||||||
local PROGRESS_FILE = 'usr/config/mining.progress'
|
local PROGRESS_FILE = 'usr/config/mining.progress'
|
||||||
local TRASH_FILE = 'usr/config/mining.trash'
|
local TRASH_FILE = 'usr/config/mining.trash'
|
||||||
|
|
||||||
if not term.isColor() then
|
|
||||||
MAX_FUEL = 20000
|
|
||||||
end
|
|
||||||
|
|
||||||
local mining = {
|
local mining = {
|
||||||
diameter = 1,
|
diameter = 1,
|
||||||
chunkIndex = 0,
|
chunkIndex = 0,
|
||||||
chunks = -1,
|
chunks = -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
local trash
|
local trash, boreDirection, unload
|
||||||
local boreDirection
|
|
||||||
|
|
||||||
function getChunkCoordinates(diameter, index, x, z)
|
local function getChunkCoordinates(diameter, index, x, z)
|
||||||
local dirs = { -- circumference of grid
|
local dirs = { -- circumference of grid
|
||||||
{ xd = 0, zd = 1, heading = 1 }, -- south
|
{ xd = 0, zd = 1, heading = 1 }, -- south
|
||||||
{ xd = -1, zd = 0, heading = 2 },
|
{ xd = -1, zd = 0, heading = 2 },
|
||||||
@@ -68,13 +63,13 @@ function getChunkCoordinates(diameter, index, x, z)
|
|||||||
dirs[4].z = z
|
dirs[4].z = z
|
||||||
return dirs[4]
|
return dirs[4]
|
||||||
end
|
end
|
||||||
dir = dirs[math.floor(index / (diameter - 1)) + 1]
|
local dir = dirs[math.floor(index / (diameter - 1)) + 1]
|
||||||
dir.x = x + dir.xd * 16
|
dir.x = x + dir.xd * 16
|
||||||
dir.z = z + dir.zd * 16
|
dir.z = z + dir.zd * 16
|
||||||
return dir
|
return dir
|
||||||
end
|
end
|
||||||
|
|
||||||
function getBoreLocations(x, z)
|
local function getBoreLocations(x, z)
|
||||||
|
|
||||||
local locations = {}
|
local locations = {}
|
||||||
|
|
||||||
@@ -116,7 +111,7 @@ function getBoreLocations(x, z)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get the bore location closest to the miner
|
-- get the bore location closest to the miner
|
||||||
local function getClosestLocation(points, b)
|
local function getClosestLocation(points)
|
||||||
local key = 1
|
local key = 1
|
||||||
local leastMoves = 9000
|
local leastMoves = 9000
|
||||||
for k,pt in pairs(points) do
|
for k,pt in pairs(points) do
|
||||||
@@ -134,11 +129,11 @@ local function getClosestLocation(points, b)
|
|||||||
return table.remove(points, key)
|
return table.remove(points, key)
|
||||||
end
|
end
|
||||||
|
|
||||||
function getCornerOf(c)
|
local function getCornerOf(c)
|
||||||
return math.floor(c.x / 16) * 16, math.floor(c.z / 16) * 16
|
return math.floor(c.x / 16) * 16, math.floor(c.z / 16) * 16
|
||||||
end
|
end
|
||||||
|
|
||||||
function nextChunk()
|
local function nextChunk()
|
||||||
|
|
||||||
local x, z = getCornerOf({ x = mining.x, z = mining.z })
|
local x, z = getCornerOf({ x = mining.x, z = mining.z })
|
||||||
local points = math.pow(mining.diameter, 2) - math.pow(mining.diameter-2, 2)
|
local points = math.pow(mining.diameter, 2) - math.pow(mining.diameter-2, 2)
|
||||||
@@ -168,7 +163,7 @@ function nextChunk()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function addTrash()
|
local function addTrash()
|
||||||
|
|
||||||
if not trash then
|
if not trash then
|
||||||
trash = { }
|
trash = { }
|
||||||
@@ -176,7 +171,7 @@ function addTrash()
|
|||||||
|
|
||||||
local slots = turtle.getFilledSlots()
|
local slots = turtle.getFilledSlots()
|
||||||
|
|
||||||
for k,slot in pairs(slots) do
|
for _,slot in pairs(slots) do
|
||||||
trash[slot.iddmg] = true
|
trash[slot.iddmg] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -184,19 +179,18 @@ function addTrash()
|
|||||||
Util.writeTable(TRASH_FILE, trash)
|
Util.writeTable(TRASH_FILE, trash)
|
||||||
end
|
end
|
||||||
|
|
||||||
function log(text)
|
local function log(text)
|
||||||
print(text)
|
print(text)
|
||||||
Logger.log('mineWorker', text)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function status(status)
|
local function status(newStatus)
|
||||||
turtle.status = status
|
turtle.setStatus(newStatus)
|
||||||
log(status)
|
log(newStatus)
|
||||||
end
|
end
|
||||||
|
|
||||||
function refuel()
|
local function refuel()
|
||||||
if turtle.getFuelLevel() < MIN_FUEL then
|
if turtle.getFuelLevel() < MIN_FUEL then
|
||||||
local oldStatus = turtle.status
|
local oldStatus = turtle.getStatus()
|
||||||
status('refueling')
|
status('refueling')
|
||||||
|
|
||||||
if turtle.select('minecraft:coal:0') then
|
if turtle.select('minecraft:coal:0') then
|
||||||
@@ -221,7 +215,51 @@ function refuel()
|
|||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function enderChestUnload()
|
local function safeGoto(x, z, y, h)
|
||||||
|
local oldStatus = turtle.getStatus()
|
||||||
|
|
||||||
|
-- only pathfind above or around other turtles (never down)
|
||||||
|
Pathing.setBox({ x = turtle.point.x, y = turtle.point.y, z = turtle.point.z, ex = x, ey = y, ez = z })
|
||||||
|
while not turtle.pathfind({ x = x, z = z, y = y or turtle.point.y, heading = h }) do
|
||||||
|
--status('stuck')
|
||||||
|
if turtle.isAborted() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
os.sleep(3)
|
||||||
|
end
|
||||||
|
turtle.setStatus(oldStatus)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function safeGotoY(y)
|
||||||
|
local oldStatus = turtle.getStatus()
|
||||||
|
while not turtle.gotoY(y) do
|
||||||
|
status('stuck')
|
||||||
|
if turtle.isAborted() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
os.sleep(1)
|
||||||
|
end
|
||||||
|
turtle.setStatus(oldStatus)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function makeWalkableTunnel(action, tpt, pt)
|
||||||
|
if action ~= 'turn' and not Point.compare(tpt, { x = 0, z = 0 }) then -- not at source
|
||||||
|
if not Point.compare(tpt, pt) then -- not at dest
|
||||||
|
local r, block = turtle.inspectUp()
|
||||||
|
if r and not turtle.isTurtleAtSide('top') then
|
||||||
|
if block.name ~= 'minecraft:cobblestone' and
|
||||||
|
block.name ~= 'minecraft:chest' then
|
||||||
|
turtle.digUp()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local function enderChestUnload()
|
||||||
log('unloading')
|
log('unloading')
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
if not Util.tryTimed(5, function()
|
if not Util.tryTimed(5, function()
|
||||||
@@ -237,52 +275,10 @@ function enderChestUnload()
|
|||||||
turtle.digDown()
|
turtle.digDown()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
|
|
||||||
function safeGoto(x, z, y, h)
|
local function normalChestUnload()
|
||||||
local oldStatus = turtle.status
|
local oldStatus = turtle.getStatus()
|
||||||
|
|
||||||
-- only pathfind above or around other turtles (never down)
|
|
||||||
Pathing.setBox({ x = 0, y = 0, z = 0, ex = x, ey = y + 1, ez = z })
|
|
||||||
while not turtle.pathfind({ x = x, z = z, y = y or turtle.point.y, heading = h }) do
|
|
||||||
--status('stuck')
|
|
||||||
if turtle.abort then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
--os.sleep(1)
|
|
||||||
end
|
|
||||||
turtle.status = oldStatus
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function safeGotoY(y)
|
|
||||||
local oldStatus = turtle.status
|
|
||||||
while not turtle.gotoY(y) do
|
|
||||||
status('stuck')
|
|
||||||
if turtle.abort then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
os.sleep(1)
|
|
||||||
end
|
|
||||||
turtle.status = oldStatus
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function makeWalkableTunnel(action, tpt, pt)
|
|
||||||
if action ~= 'turn' and not Point.compare(tpt, { x = 0, z = 0 }) then -- not at source
|
|
||||||
if not Point.compare(tpt, pt) then -- not at dest
|
|
||||||
local r, block = turtle.inspectUp()
|
|
||||||
if r and not turtle.isTurtleAtSide('top') then
|
|
||||||
if block.name ~= 'minecraft:cobblestone' and
|
|
||||||
block.name ~= 'minecraft:chest' then
|
|
||||||
turtle.digUp()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function normalChestUnload()
|
|
||||||
local oldStatus = turtle.status
|
|
||||||
status('unloading')
|
status('unloading')
|
||||||
local pt = Util.shallowCopy(turtle.point)
|
local pt = Util.shallowCopy(turtle.point)
|
||||||
safeGotoY(0)
|
safeGotoY(0)
|
||||||
@@ -291,7 +287,7 @@ function normalChestUnload()
|
|||||||
makeWalkableTunnel(action, tpt, { x = pt.x, z = pt.z })
|
makeWalkableTunnel(action, tpt, { x = pt.x, z = pt.z })
|
||||||
end)
|
end)
|
||||||
|
|
||||||
safeGoto(0, 0)
|
safeGoto(0, 0, 0)
|
||||||
if not turtle.detectUp() then
|
if not turtle.detectUp() then
|
||||||
error('no chest')
|
error('no chest')
|
||||||
end
|
end
|
||||||
@@ -317,7 +313,7 @@ function normalChestUnload()
|
|||||||
status(oldStatus)
|
status(oldStatus)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ejectTrash()
|
local function ejectTrash()
|
||||||
|
|
||||||
local cobbleSlotCount = 0
|
local cobbleSlotCount = 0
|
||||||
|
|
||||||
@@ -325,7 +321,7 @@ function ejectTrash()
|
|||||||
if slot.iddmg == 'minecraft:cobblestone:0' then
|
if slot.iddmg == 'minecraft:cobblestone:0' then
|
||||||
if cobbleSlotCount == 0 and slot.count > 36 then
|
if cobbleSlotCount == 0 and slot.count > 36 then
|
||||||
turtle.select(slot.index)
|
turtle.select(slot.index)
|
||||||
turtle.dropDown(32)
|
turtle.dropDown(slot.count - 36)
|
||||||
end
|
end
|
||||||
cobbleSlotCount = cobbleSlotCount + 1
|
cobbleSlotCount = cobbleSlotCount + 1
|
||||||
end
|
end
|
||||||
@@ -340,7 +336,35 @@ function ejectTrash()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mineable(action)
|
local function checkSpace()
|
||||||
|
if turtle.getItemCount(16) > 0 then
|
||||||
|
refuel()
|
||||||
|
local oldStatus = turtle.getStatus()
|
||||||
|
status('condensing')
|
||||||
|
ejectTrash()
|
||||||
|
turtle.condense()
|
||||||
|
local lastSlot = 16
|
||||||
|
if boreDirection == 'down' then
|
||||||
|
lastSlot = 15
|
||||||
|
end
|
||||||
|
if turtle.getItemCount(lastSlot) > 0 then
|
||||||
|
unload()
|
||||||
|
end
|
||||||
|
status(oldStatus)
|
||||||
|
turtle.select(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function collectDrops(suckAction)
|
||||||
|
for _ = 1, 50 do
|
||||||
|
if not suckAction() then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
checkSpace()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mineable(action)
|
||||||
local r, block = action.inspect()
|
local r, block = action.inspect()
|
||||||
if not r then
|
if not r then
|
||||||
return false
|
return false
|
||||||
@@ -375,12 +399,12 @@ function mineable(action)
|
|||||||
return block.name
|
return block.name
|
||||||
end
|
end
|
||||||
|
|
||||||
function fortuneDig(action, blockName)
|
local function fortuneDig(action, blockName)
|
||||||
if options.fortunePick.value and fortuneBlocks[blockName] then
|
if options.fortunePick.value and fortuneBlocks[blockName] then
|
||||||
turtle.select('cctweaks:toolHost')
|
turtle.select('cctweaks:toolHost')
|
||||||
turtle.equipRight()
|
turtle.equipRight()
|
||||||
turtle.select(options.fortunePick.value)
|
turtle.select(options.fortunePick.value)
|
||||||
repeat until not turtle.dig()
|
repeat until not action.dig()
|
||||||
turtle.select('minecraft:diamond_pickaxe')
|
turtle.select('minecraft:diamond_pickaxe')
|
||||||
turtle.equipRight()
|
turtle.equipRight()
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
@@ -388,7 +412,7 @@ function fortuneDig(action, blockName)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mine(action)
|
local function mine(action)
|
||||||
local blockName = mineable(action)
|
local blockName = mineable(action)
|
||||||
if blockName then
|
if blockName then
|
||||||
checkSpace()
|
checkSpace()
|
||||||
@@ -399,7 +423,7 @@ function mine(action)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function bore()
|
local function bore()
|
||||||
|
|
||||||
local loc = turtle.point
|
local loc = turtle.point
|
||||||
local level = loc.y
|
local level = loc.y
|
||||||
@@ -409,7 +433,7 @@ function bore()
|
|||||||
boreDirection = 'down'
|
boreDirection = 'down'
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
if turtle.abort then
|
if turtle.isAborted() then
|
||||||
status('aborting')
|
status('aborting')
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -417,10 +441,6 @@ function bore()
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
if turtle.point.y < -2 then
|
|
||||||
-- turtle.setDigPolicy(turtle.digPolicies.turtleSafe)
|
|
||||||
end
|
|
||||||
|
|
||||||
mine(turtle.getAction('down'))
|
mine(turtle.getAction('down'))
|
||||||
if not Util.tryTimed(3, turtle.down) then
|
if not Util.tryTimed(3, turtle.down) then
|
||||||
break
|
break
|
||||||
@@ -445,19 +465,15 @@ function bore()
|
|||||||
turtle.turnLeft()
|
turtle.turnLeft()
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
if turtle.abort then
|
if turtle.isAborted() then
|
||||||
status('aborting')
|
status('aborting')
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if turtle.point.y > -2 then
|
|
||||||
-- turtle.setDigPolicy(turtle.digPolicies.turtleSafe)
|
|
||||||
end
|
|
||||||
|
|
||||||
while not Util.tryTimed(3, turtle.up) do
|
while not Util.tryTimed(3, turtle.up) do
|
||||||
status('stuck')
|
status('stuck')
|
||||||
end
|
end
|
||||||
if turtle.status == 'stuck' then
|
if turtle.getStatus() == 'stuck' then
|
||||||
status('boring up')
|
status('boring up')
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -482,34 +498,6 @@ function bore()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function checkSpace()
|
|
||||||
if turtle.getItemCount(16) > 0 then
|
|
||||||
refuel()
|
|
||||||
local oldStatus = turtle.status
|
|
||||||
status('condensing')
|
|
||||||
ejectTrash()
|
|
||||||
turtle.condense()
|
|
||||||
local lastSlot = 16
|
|
||||||
if boreDirection == 'down' then
|
|
||||||
lastSlot = 15
|
|
||||||
end
|
|
||||||
if turtle.getItemCount(lastSlot) > 0 then
|
|
||||||
unload()
|
|
||||||
end
|
|
||||||
status(oldStatus)
|
|
||||||
turtle.select(1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function collectDrops(suckAction)
|
|
||||||
for i = 1, 50 do
|
|
||||||
if not suckAction() then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
checkSpace()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Point.compare(pta, ptb)
|
function Point.compare(pta, ptb)
|
||||||
if pta.x == ptb.x and pta.z == ptb.z then
|
if pta.x == ptb.x and pta.z == ptb.z then
|
||||||
if pta.y and ptb.y then
|
if pta.y and ptb.y then
|
||||||
@@ -520,15 +508,15 @@ function Point.compare(pta, ptb)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function inspect(action, name)
|
local function inspect(action, name)
|
||||||
local r, block = action.inspect()
|
local r, block = action.inspect()
|
||||||
if r and block.name == name then
|
if r and block.name == name then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function boreCommand()
|
local function boreCommand()
|
||||||
local pt = getClosestLocation(mining.locations, turtle.point)
|
local pt = getClosestLocation(mining.locations)
|
||||||
|
|
||||||
turtle.setMoveCallback(function(action, tpt)
|
turtle.setMoveCallback(function(action, tpt)
|
||||||
makeWalkableTunnel(action, tpt, pt)
|
makeWalkableTunnel(action, tpt, pt)
|
||||||
@@ -566,6 +554,7 @@ if not Util.getOptions(options, args) then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO: this won't work - need to Util.merge file into mining
|
||||||
mining.depth = options.depth.value
|
mining.depth = options.depth.value
|
||||||
mining.chunks = options.chunks.value
|
mining.chunks = options.chunks.value
|
||||||
|
|
||||||
@@ -628,16 +617,14 @@ turtle.run(function()
|
|||||||
turtle.reset()
|
turtle.reset()
|
||||||
turtle.setPolicy(turtle.policies.digAttack)
|
turtle.setPolicy(turtle.policies.digAttack)
|
||||||
turtle.setDigPolicy(turtle.digPolicies.turtleSafe)
|
turtle.setDigPolicy(turtle.digPolicies.turtleSafe)
|
||||||
|
|
||||||
unload()
|
unload()
|
||||||
status('mining')
|
status('mining')
|
||||||
|
|
||||||
local s, m = pcall(function() main() end)
|
local s, m = pcall(main)
|
||||||
if not s and m then
|
if not s and m then
|
||||||
printError(m)
|
_G.printError(m)
|
||||||
end
|
end
|
||||||
|
turtle.abort(false)
|
||||||
turtle.abort = false
|
|
||||||
safeGotoY(0)
|
safeGotoY(0)
|
||||||
safeGoto(0, 0, 0, 0)
|
safeGoto(0, 0, 0, 0)
|
||||||
unload()
|
unload()
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local ChestAdapter = require('chestAdapter18')
|
local InventoryAdapter = require('inventoryAdapter')
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local MEAdapter = require('meAdapter')
|
local UI = require('ui')
|
||||||
local RefinedAdapter = require('refinedAdapter')
|
local Util = require('util')
|
||||||
local UI = require('ui')
|
|
||||||
local Util = require('util')
|
|
||||||
|
|
||||||
local storage = RefinedAdapter()
|
local colors = _G.colors
|
||||||
if not storage:isValid() then
|
local multishell = _ENV.multishell
|
||||||
storage = MEAdapter({ auto = true })
|
|
||||||
if not storage:isValid() then
|
|
||||||
storage = ChestAdapter()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not storage:isValid() then
|
local storage = InventoryAdapter.wrap()
|
||||||
error('Not connected to a storage device')
|
if not storage then
|
||||||
|
error('Not connected to a valid inventory')
|
||||||
end
|
end
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'Storage Activity')
|
multishell.setTitle(multishell.getCurrent(), 'Storage Activity')
|
||||||
@@ -26,8 +20,9 @@ local changedPage = UI.Page {
|
|||||||
grid = UI.Grid {
|
grid = UI.Grid {
|
||||||
ey = -6,
|
ey = -6,
|
||||||
columns = {
|
columns = {
|
||||||
{ heading = 'Qty', key = 'count', width = 5 },
|
{ heading = 'Qty', key = 'count', width = 5 },
|
||||||
{ heading = 'Change', key = 'change', width = 6 },
|
{ heading = 'Change', key = 'change', width = 6 },
|
||||||
|
{ heading = 'Rate', key = 'rate', width = 6 },
|
||||||
{ heading = 'Name', key = 'displayName' },
|
{ heading = 'Name', key = 'displayName' },
|
||||||
},
|
},
|
||||||
sortColumn = 'displayName',
|
sortColumn = 'displayName',
|
||||||
@@ -66,6 +61,7 @@ function changedPage.grid:getDisplayValues(row)
|
|||||||
if row.change < 0 then
|
if row.change < 0 then
|
||||||
ind = ''
|
ind = ''
|
||||||
end
|
end
|
||||||
|
|
||||||
row.change = ind .. Util.toBytes(row.change)
|
row.change = ind .. Util.toBytes(row.change)
|
||||||
row.count = Util.toBytes(row.count)
|
row.count = Util.toBytes(row.count)
|
||||||
|
|
||||||
@@ -73,7 +69,6 @@ function changedPage.grid:getDisplayValues(row)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function changedPage:eventHandler(event)
|
function changedPage:eventHandler(event)
|
||||||
|
|
||||||
if event.type == 'reset' then
|
if event.type == 'reset' then
|
||||||
self.lastItems = nil
|
self.lastItems = nil
|
||||||
self.grid:setValues({ })
|
self.grid:setValues({ })
|
||||||
@@ -104,8 +99,8 @@ function changedPage:refresh()
|
|||||||
local t = storage:listItems()
|
local t = storage:listItems()
|
||||||
|
|
||||||
if not t or Util.empty(t) then
|
if not t or Util.empty(t) then
|
||||||
self:clear()
|
self.grid:clear()
|
||||||
self:centeredWrite(math.ceil(self.height/2), 'Communication failure')
|
self.grid:centeredWrite(math.ceil(self.height/2), 'Communication failure')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -115,9 +110,12 @@ function changedPage:refresh()
|
|||||||
|
|
||||||
if not self.lastItems then
|
if not self.lastItems then
|
||||||
self.lastItems = t
|
self.lastItems = t
|
||||||
|
self.timestamp = os.clock()
|
||||||
self.grid:setValues({ })
|
self.grid:setValues({ })
|
||||||
else
|
else
|
||||||
local changedItems = {}
|
self.elapsed = os.clock() - self.timestamp
|
||||||
|
local changedItems = { }
|
||||||
|
local found
|
||||||
for _,v in pairs(self.lastItems) do
|
for _,v in pairs(self.lastItems) do
|
||||||
found = false
|
found = false
|
||||||
for k2,v2 in pairs(t) do
|
for k2,v2 in pairs(t) do
|
||||||
@@ -141,13 +139,14 @@ function changedPage:refresh()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- No items left
|
-- No items left
|
||||||
for k,v in pairs(t) do
|
for _,v in pairs(t) do
|
||||||
v.lastCount = 0
|
v.lastCount = 0
|
||||||
table.insert(changedItems, v)
|
table.insert(changedItems, v)
|
||||||
end
|
end
|
||||||
|
|
||||||
for k,v in pairs(changedItems) do
|
for _,v in pairs(changedItems) do
|
||||||
v.change = v.count - v.lastCount
|
v.change = v.count - v.lastCount
|
||||||
|
v.rate = Util.round(60 / self.elapsed * v.change, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.grid:setValues(changedItems)
|
self.grid:setValues(changedItems)
|
||||||
@@ -161,4 +160,5 @@ Event.onInterval(5, function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
UI:setPage(changedPage)
|
UI:setPage(changedPage)
|
||||||
|
changedPage:draw()
|
||||||
UI:pullEvents()
|
UI:pullEvents()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local Logger = require('logger')
|
local Logger = require('logger')
|
||||||
@@ -8,6 +8,10 @@ local Point = require('point')
|
|||||||
local TableDB = require('tableDB')
|
local TableDB = require('tableDB')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local device = _G.device
|
||||||
|
local os = _G.os
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
A supplier turtle for the builder turtle. For larger builds, use
|
A supplier turtle for the builder turtle. For larger builds, use
|
||||||
ender modems.
|
ender modems.
|
||||||
@@ -87,7 +91,7 @@ function Builder:dumpInventoryWithCheck()
|
|||||||
print('Press enter to continue')
|
print('Press enter to continue')
|
||||||
--turtle.setHeading(0)
|
--turtle.setHeading(0)
|
||||||
self.ready = false
|
self.ready = false
|
||||||
read()
|
_G.read()
|
||||||
end
|
end
|
||||||
self.ready = true
|
self.ready = true
|
||||||
end
|
end
|
||||||
@@ -95,7 +99,7 @@ end
|
|||||||
function Builder:autocraft(supplies)
|
function Builder:autocraft(supplies)
|
||||||
local t = { }
|
local t = { }
|
||||||
|
|
||||||
for i,s in pairs(supplies) do
|
for _,s in pairs(supplies) do
|
||||||
local key = s.id .. ':' .. s.dmg
|
local key = s.id .. ':' .. s.dmg
|
||||||
local item = t[key]
|
local item = t[key]
|
||||||
if not item then
|
if not item then
|
||||||
@@ -214,7 +218,6 @@ local function moveTowardsZ(dz)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Builder:finish()
|
function Builder:finish()
|
||||||
|
|
||||||
Builder.resupplying = true
|
Builder.resupplying = true
|
||||||
Builder.ready = false
|
Builder.ready = false
|
||||||
if turtle.gotoLocation('supplies') then
|
if turtle.gotoLocation('supplies') then
|
||||||
@@ -227,9 +230,8 @@ function Builder:finish()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Builder:gotoBuilder()
|
function Builder:gotoBuilder()
|
||||||
|
|
||||||
if Builder.lastPoint then
|
if Builder.lastPoint then
|
||||||
turtle.status = 'tracking'
|
turtle.setStatus('tracking')
|
||||||
while true do
|
while true do
|
||||||
local pt = Point.copy(Builder.lastPoint)
|
local pt = Point.copy(Builder.lastPoint)
|
||||||
pt.y = pt.y + 3
|
pt.y = pt.y + 3
|
||||||
@@ -261,139 +263,136 @@ function Builder:gotoBuilder()
|
|||||||
end
|
end
|
||||||
|
|
||||||
Message.addHandler('builder',
|
Message.addHandler('builder',
|
||||||
function(h, id, msg, distance)
|
function(_, id, msg)
|
||||||
if not id or id ~= __BUILDER_ID then
|
if not id or id ~= __BUILDER_ID then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not Builder.resupplying then
|
if not Builder.resupplying then
|
||||||
local pt = msg.contents
|
local pt = msg.contents
|
||||||
pt.y = pt.y + 3
|
pt.y = pt.y + 3
|
||||||
|
|
||||||
turtle.status = 'supervising'
|
turtle.setStatus('supervising')
|
||||||
turtle.gotoYfirst(pt)
|
turtle.gotoYfirst(pt)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Message.addHandler('supplyList',
|
Message.addHandler('supplyList',
|
||||||
function(h, id, msg, distance)
|
function(_, id, msg)
|
||||||
if not id or id ~= __BUILDER_ID then
|
if not id or id ~= __BUILDER_ID then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
turtle.status = 'resupplying'
|
turtle.setStatus('resupplying')
|
||||||
Builder.resupplying = true
|
Builder.resupplying = true
|
||||||
Builder.slots = msg.contents.slots
|
Builder.slots = msg.contents.slots
|
||||||
Builder.slotUid = msg.contents.uid
|
Builder.slotUid = msg.contents.uid
|
||||||
|
|
||||||
Builder:log('Received supply list ' .. Builder.slotUid)
|
Builder:log('Received supply list ' .. Builder.slotUid)
|
||||||
|
|
||||||
os.sleep(0)
|
os.sleep(0)
|
||||||
if not turtle.gotoLocation('supplies') then
|
if not turtle.gotoLocation('supplies') then
|
||||||
Builder:log('Failed to go to supply location')
|
Builder:log('Failed to go to supply location')
|
||||||
self.ready = false
|
Builder.ready = false
|
||||||
Event.exitPullEvents()
|
Event.exitPullEvents()
|
||||||
end
|
end
|
||||||
turtle.setHeading(1)
|
turtle.setHeading(1)
|
||||||
os.sleep(.2) -- random 'Computer is not connected' error...
|
os.sleep(.2) -- random 'Computer is not connected' error...
|
||||||
Builder:dumpInventoryWithCheck()
|
Builder:dumpInventoryWithCheck()
|
||||||
Builder:refuel()
|
Builder:refuel()
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local supplies = Builder:getSupplies()
|
local supplies = Builder:getSupplies()
|
||||||
if #supplies == 0 then
|
if #supplies == 0 then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
Builder:autocraft(supplies)
|
Builder:autocraft(supplies)
|
||||||
turtle.status = 'waiting'
|
turtle.setStatus('waiting')
|
||||||
os.sleep(5)
|
os.sleep(5)
|
||||||
end
|
end
|
||||||
Builder:log('Got all supplies')
|
Builder:log('Got all supplies')
|
||||||
os.sleep(0)
|
os.sleep(0)
|
||||||
Builder:gotoBuilder()
|
Builder:gotoBuilder()
|
||||||
Builder.resupplying = false
|
Builder.resupplying = false
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Message.addHandler('needSupplies',
|
Message.addHandler('needSupplies',
|
||||||
function(h, id, msg, distance)
|
function(_, id, msg)
|
||||||
if not id or id ~= __BUILDER_ID then
|
if not id or id ~= __BUILDER_ID then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if Builder.resupplying or msg.contents.uid ~= Builder.slotUid then
|
if Builder.resupplying or msg.contents.uid ~= Builder.slotUid then
|
||||||
|
Builder:log('No supplies ready')
|
||||||
|
Message.send(__BUILDER_ID, 'gotSupplies')
|
||||||
|
else
|
||||||
|
turtle.setStatus('supplying')
|
||||||
|
Builder:log('Supplying')
|
||||||
|
os.sleep(0)
|
||||||
|
|
||||||
Builder:log('No supplies ready')
|
local pt = msg.contents.point
|
||||||
|
pt.y = turtle.getPoint().y
|
||||||
Message.send(__BUILDER_ID, 'gotSupplies')
|
pt.heading = nil
|
||||||
else
|
if not turtle.gotoYfirst(pt) then -- location of builder
|
||||||
turtle.status = 'supplying'
|
Builder.resupplying = true
|
||||||
Builder:log('Supplying')
|
Message.send(__BUILDER_ID, 'gotSupplies')
|
||||||
os.sleep(0)
|
os.sleep(0)
|
||||||
|
if not turtle.gotoLocation('supplies') then
|
||||||
local pt = msg.contents.point
|
Builder:log('failed to go to supply location')
|
||||||
pt.y = turtle.getPoint().y
|
Event.exitPullEvents()
|
||||||
pt.heading = nil
|
end
|
||||||
if not turtle.gotoYfirst(pt) then -- location of builder
|
|
||||||
Builder.resupplying = true
|
|
||||||
Message.send(__BUILDER_ID, 'gotSupplies')
|
|
||||||
os.sleep(0)
|
|
||||||
if not turtle.gotoLocation('supplies') then
|
|
||||||
Builder:log('failed to go to supply location')
|
|
||||||
--self.ready = false
|
|
||||||
Event.exitPullEvents()
|
|
||||||
end
|
|
||||||
turtle.setHeading(1)
|
turtle.setHeading(1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
pt.y = pt.y - 2 -- location where builder should go for the chest to be above
|
pt.y = pt.y - 2 -- location where builder should go for the chest to be above
|
||||||
|
|
||||||
turtle.select(15)
|
turtle.select(15)
|
||||||
turtle.placeDown()
|
turtle.placeDown()
|
||||||
os.sleep(.1) -- random computer not connected error
|
os.sleep(.1) -- random computer not connected error
|
||||||
local p = ChestProvider({ direction = 'up', wrapSide = 'bottom' })
|
local p = ChestProvider({ direction = 'up', wrapSide = 'bottom' })
|
||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
p:insert(i, 64)
|
p:insert(i, 64)
|
||||||
end
|
end
|
||||||
|
|
||||||
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true, point = pt })
|
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true, point = pt })
|
||||||
|
|
||||||
Message.waitForMessage('thanks', 5, __BUILDER_ID)
|
Message.waitForMessage('thanks', 5, __BUILDER_ID)
|
||||||
--os.sleep(0)
|
--os.sleep(0)
|
||||||
|
|
||||||
--p.condenseItems()
|
--p.condenseItems()
|
||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
p:extract(i, 64)
|
p:extract(i, 64)
|
||||||
end
|
end
|
||||||
turtle.digDown()
|
turtle.digDown()
|
||||||
turtle.status = 'waiting'
|
turtle.setStatus('waiting')
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Message.addHandler('finished',
|
Message.addHandler('finished',
|
||||||
function(h, id)
|
function(_, id)
|
||||||
if not id or id ~= __BUILDER_ID then
|
if not id or id ~= __BUILDER_ID then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
Builder:finish()
|
Builder:finish()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Event.on('turtle_abort',
|
Event.on('turtle_abort',
|
||||||
function()
|
function()
|
||||||
turtle.abort = false
|
turtle.abort(false)
|
||||||
turtle.status = 'aborting'
|
turtle.setStatus('aborting')
|
||||||
Builder:finish()
|
Builder:finish()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local function onTheWay() -- parallel routine
|
local function onTheWay() -- parallel routine
|
||||||
while true do
|
while true do
|
||||||
local e, side, _id, id, msg, distance = os.pullEvent('modem_message')
|
local _, _, _, id, msg, _ = os.pullEvent('modem_message')
|
||||||
if Builder.ready then
|
if Builder.ready then
|
||||||
if id == __BUILDER_ID and msg and msg.type then
|
if id == __BUILDER_ID and msg and msg.type then
|
||||||
if msg.type == 'needSupplies' then
|
if msg.type == 'needSupplies' then
|
||||||
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true })
|
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true })
|
||||||
elseif msg.type == 'builder' then
|
elseif msg.type == 'builder' then
|
||||||
Builder.lastPoint = msg.contents
|
Builder.lastPoint = msg.contents
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
22
apps/termShare.lua
Normal file
22
apps/termShare.lua
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
local device = _G.device
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
local term = _G.term
|
||||||
|
|
||||||
|
-- list this terminal in the devices list so it's available via
|
||||||
|
-- peripheral sharing
|
||||||
|
|
||||||
|
local args = { ... }
|
||||||
|
local name = args[1] or error('Syntax: termShare [device name] <title>')
|
||||||
|
local title = args[2]
|
||||||
|
|
||||||
|
device[name] = term.current()
|
||||||
|
device[name].name = name
|
||||||
|
device[name].side = name
|
||||||
|
device[name].type = 'terminal'
|
||||||
|
|
||||||
|
if title then
|
||||||
|
multishell.setTitle(multishell.getCurrent(), title)
|
||||||
|
end
|
||||||
|
os.pullEvent('terminate')
|
||||||
|
os.queueEvent('peripheral_detach', name)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Requirements:
|
Requirements:
|
||||||
@@ -6,7 +6,7 @@ requireInjector(getfenv(1))
|
|||||||
Area around turtle must be flat and can only be dirt or grass
|
Area around turtle must be flat and can only be dirt or grass
|
||||||
(10 blocks in each direction from turtle)
|
(10 blocks in each direction from turtle)
|
||||||
Turtle must have: crafting table, chest
|
Turtle must have: crafting table, chest
|
||||||
Turtle must have a pick equipped on the left side
|
Turtle must have a pick equipped
|
||||||
|
|
||||||
Optional:
|
Optional:
|
||||||
Add additional sapling types that can grow with a single sapling
|
Add additional sapling types that can grow with a single sapling
|
||||||
@@ -20,12 +20,12 @@ requireInjector(getfenv(1))
|
|||||||
place the turtle in the original position before restarting the program.
|
place the turtle in the original position before restarting the program.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
local ChestAdapter = require('chestAdapter18')
|
local Point = require('point')
|
||||||
local Craft = require('turtle.craft')
|
local Util = require('util')
|
||||||
local Level = require('turtle.level')
|
|
||||||
local Pathing = require('turtle.pathfind')
|
local os = _G.os
|
||||||
local Point = require('point')
|
local read = _G.read
|
||||||
local Util = require('util')
|
local turtle = _G.turtle
|
||||||
|
|
||||||
local FUEL_BASE = 0
|
local FUEL_BASE = 0
|
||||||
local FUEL_DIRE = FUEL_BASE + 10
|
local FUEL_DIRE = FUEL_BASE + 10
|
||||||
@@ -76,9 +76,6 @@ local state = Util.readTable('usr/config/treefarm') or {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local clock = os.clock()
|
local clock = os.clock()
|
||||||
local recipes = Util.readTable('usr/etc/recipes.db') or { }
|
|
||||||
|
|
||||||
Craft.setRecipes(recipes)
|
|
||||||
|
|
||||||
local function inspect(fn)
|
local function inspect(fn)
|
||||||
local s, item = fn()
|
local s, item = fn()
|
||||||
@@ -121,28 +118,21 @@ local function safePlaceBlock(item)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function craftItem(item, qty)
|
local function craftItem(item, qty)
|
||||||
|
local success, msg
|
||||||
local success
|
|
||||||
|
|
||||||
if safePlaceBlock(CHEST) then
|
if safePlaceBlock(CHEST) then
|
||||||
|
|
||||||
if turtle.equip('left', 'minecraft:crafting_table') then
|
Util.print('Crafting %d %s', (qty or 1), item)
|
||||||
|
success, msg = turtle.craftItem(item, qty or 1, {
|
||||||
local chestAdapter = ChestAdapter({
|
|
||||||
wrapSide = 'top',
|
wrapSide = 'top',
|
||||||
direction = 'down',
|
direction = 'down',
|
||||||
})
|
})
|
||||||
if not chestAdapter:isValid() then
|
repeat until not turtle.suckUp()
|
||||||
print('invalid chestAdapter')
|
|
||||||
read()
|
|
||||||
end
|
|
||||||
|
|
||||||
Util.print('Crafting %d %s', (qty or 1), item)
|
if not success then
|
||||||
success = Craft.craftRecipe(recipes[item], qty or 1, chestAdapter)
|
print(msg)
|
||||||
|
|
||||||
repeat until not turtle.suckUp()
|
|
||||||
end
|
end
|
||||||
turtle.equip('left', 'minecraft:diamond_pickaxe')
|
|
||||||
turtle.digUp()
|
turtle.digUp()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -201,7 +191,7 @@ local function makeCharcoal()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getLogSlot(slots)
|
local function getLogSlot()
|
||||||
local maxslot = { count = 0 }
|
local maxslot = { count = 0 }
|
||||||
for k,slot in pairs(slots) do
|
for k,slot in pairs(slots) do
|
||||||
if string.match(k, 'minecraft:log') then
|
if string.match(k, 'minecraft:log') then
|
||||||
@@ -214,7 +204,8 @@ local function makeCharcoal()
|
|||||||
end
|
end
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
local slots = turtle.getSummedInventory()
|
slots = turtle.getSummedInventory()
|
||||||
|
|
||||||
local charcoal = slots[CHARCOAL].count
|
local charcoal = slots[CHARCOAL].count
|
||||||
local slot = getLogSlot(slots)
|
local slot = getLogSlot(slots)
|
||||||
|
|
||||||
@@ -266,7 +257,7 @@ local function getCobblestone(count)
|
|||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
turtle.digDown()
|
turtle.digDown()
|
||||||
turtle.down()
|
turtle.down()
|
||||||
for i = 1, 4 do
|
for _ = 1, 4 do
|
||||||
if inspect(turtle.inspect) == STONE then
|
if inspect(turtle.inspect) == STONE then
|
||||||
turtle.dig()
|
turtle.dig()
|
||||||
end
|
end
|
||||||
@@ -281,7 +272,7 @@ local function getCobblestone(count)
|
|||||||
|
|
||||||
until turtle.getItemCount(COBBLESTONE) >= count
|
until turtle.getItemCount(COBBLESTONE) >= count
|
||||||
|
|
||||||
turtle.gotoPoint(pt)
|
turtle._goto(pt)
|
||||||
turtle.placeDown(DIRT)
|
turtle.placeDown(DIRT)
|
||||||
|
|
||||||
turtle.drop(DIRT)
|
turtle.drop(DIRT)
|
||||||
@@ -297,8 +288,8 @@ local function createFurnace()
|
|||||||
print('Adding a furnace')
|
print('Adding a furnace')
|
||||||
getCobblestone(8)
|
getCobblestone(8)
|
||||||
|
|
||||||
if craftItem(FURNACE) then
|
if turtle.has(FURNACE) or craftItem(FURNACE) then
|
||||||
turtle.drop(COBBLESTONE)
|
-- turtle.drop(COBBLESTONE)
|
||||||
local furnacePt = { x = GRID.BL.x + 2, y = 1, z = GRID.BL.z + 2 }
|
local furnacePt = { x = GRID.BL.x + 2, y = 1, z = GRID.BL.z + 2 }
|
||||||
turtle.placeAt(furnacePt, FURNACE)
|
turtle.placeAt(furnacePt, FURNACE)
|
||||||
setState('furnace', furnacePt)
|
setState('furnace', furnacePt)
|
||||||
@@ -319,7 +310,9 @@ local function createPerimeter()
|
|||||||
print('Creating a perimeter')
|
print('Creating a perimeter')
|
||||||
|
|
||||||
getCobblestone(GRID_WIDTH * 2 + 1)
|
getCobblestone(GRID_WIDTH * 2 + 1)
|
||||||
cook(COBBLESTONE, 2, STONE, OAK_PLANK, 2)
|
if not turtle.has(STONE, 2) then
|
||||||
|
cook(COBBLESTONE, 2, STONE, OAK_PLANK, 2)
|
||||||
|
end
|
||||||
turtle.refuel(OAK_PLANK)
|
turtle.refuel(OAK_PLANK)
|
||||||
|
|
||||||
turtle.pathfind(GRID.BL)
|
turtle.pathfind(GRID.BL)
|
||||||
@@ -350,35 +343,32 @@ local function createPerimeter()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function createChests()
|
local function createChests()
|
||||||
if state.chest_1 then
|
if state.chest then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if state.perimeter and
|
if state.perimeter and
|
||||||
turtle.getFuelLevel() > FUEL_GOOD and
|
turtle.getFuelLevel() > FUEL_GOOD and
|
||||||
Craft.canCraft(CHEST, 4, turtle.getSummedInventory()) then
|
turtle.canCraft(CHEST, 4, turtle.getSummedInventory()) then
|
||||||
|
|
||||||
print('Adding storage')
|
print('Adding storage')
|
||||||
if craftItem(CHEST, 4) then
|
if turtle.has(CHEST, 2) or craftItem(CHEST, 2) then
|
||||||
|
|
||||||
local pt = Point.copy(GRID.BL)
|
local pt = Point.copy(GRID.BL)
|
||||||
pt.x = pt.x + 1
|
pt.x = pt.x + 1
|
||||||
pt.y = pt.y - 1
|
pt.y = pt.y - 1
|
||||||
|
|
||||||
for i = 1, 2 do
|
pt.z = pt.z + 1
|
||||||
pt.z = pt.z + 1
|
|
||||||
|
|
||||||
turtle.digDownAt(pt)
|
turtle.digDownAt(pt)
|
||||||
turtle.placeDown(CHEST)
|
turtle.placeDown(CHEST)
|
||||||
|
|
||||||
pt.z = pt.z + 1
|
pt.z = pt.z + 1
|
||||||
|
|
||||||
turtle.digDownAt(pt)
|
turtle.digDownAt(pt)
|
||||||
turtle.placeDown(CHEST)
|
turtle.placeDown(CHEST)
|
||||||
|
|
||||||
setState('chest_' .. i, Util.shallowCopy(pt))
|
setState('chest', Util.shallowCopy(pt))
|
||||||
|
|
||||||
pt.z = pt.z + 1
|
|
||||||
end
|
|
||||||
turtle.drop(DIRT)
|
turtle.drop(DIRT)
|
||||||
turtle.refuel(OAK_PLANK)
|
turtle.refuel(OAK_PLANK)
|
||||||
end
|
end
|
||||||
@@ -388,24 +378,27 @@ end
|
|||||||
|
|
||||||
local function dropOffItems()
|
local function dropOffItems()
|
||||||
|
|
||||||
if state.chest_1 then
|
if state.chest then
|
||||||
local slots = turtle.getSummedInventory()
|
local slots = turtle.getSummedInventory()
|
||||||
|
|
||||||
if state.chest_1 and
|
if state.chest and
|
||||||
slots[CHARCOAL] and
|
slots[CHARCOAL] and
|
||||||
slots[CHARCOAL].count >= MIN_CHARCOAL and
|
slots[CHARCOAL].count >= MIN_CHARCOAL and
|
||||||
(turtle.getItemCount('minecraft:log') > 0 or
|
(turtle.getItemCount('minecraft:log') > 0 or
|
||||||
turtle.getItemCount('minecraft:log2') > 0) then
|
turtle.getItemCount('minecraft:log2') > 0) then
|
||||||
|
|
||||||
print('Storing logs')
|
print('Storing logs')
|
||||||
turtle.pathfind(Point.above(state.chest_1))
|
turtle.pathfind(Point.above(state.chest))
|
||||||
turtle.dropDown('minecraft:log')
|
turtle.dropDown('minecraft:log')
|
||||||
turtle.dropDown('minecraft:log2')
|
turtle.dropDown('minecraft:log2')
|
||||||
end
|
|
||||||
|
|
||||||
if slots[APPLE] then
|
for _, sapling in pairs(ALL_SAPLINGS) do
|
||||||
print('Storing apples')
|
if slots[sapling] and slots[sapling].count > MAX_SAPLINGS then
|
||||||
turtle.dropDownAt(state.chest_2, APPLE)
|
turtle.dropDown(sapling, slots[sapling].count - MAX_SAPLINGS)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
turtle.dropDown(APPLE)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -430,11 +423,11 @@ local function placeTorches()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if turtle.getFuelLevel() > 100 and
|
if turtle.getFuelLevel() > 100 and
|
||||||
Craft.canCraft(TORCH, 4, turtle.getSummedInventory()) then
|
turtle.canCraft(TORCH, 4, turtle.getSummedInventory()) then
|
||||||
|
|
||||||
print('Placing torches')
|
print('Placing torches')
|
||||||
|
|
||||||
if craftItem(TORCH, 4) then
|
if turtle.has(TORCH, 4) or craftItem(TORCH, 4) then
|
||||||
local pts = { }
|
local pts = { }
|
||||||
for x = -4, 4, 8 do
|
for x = -4, 4, 8 do
|
||||||
for z = -4, 4, 8 do
|
for z = -4, 4, 8 do
|
||||||
@@ -493,7 +486,7 @@ local function fellTree(pt)
|
|||||||
desperateRefuel(FUEL_DIRE)
|
desperateRefuel(FUEL_DIRE)
|
||||||
|
|
||||||
if turtle.digUpAt(Point.above(pt)) then
|
if turtle.digUpAt(Point.above(pt)) then
|
||||||
Level(
|
turtle.level(
|
||||||
{ x = GRID_WIDTH-1, y = 1, z = GRID_WIDTH-1 },
|
{ x = GRID_WIDTH-1, y = 1, z = GRID_WIDTH-1 },
|
||||||
{ x = -(GRID_WIDTH-1), y = 50, z = -(GRID_WIDTH-1) },
|
{ x = -(GRID_WIDTH-1), y = 50, z = -(GRID_WIDTH-1) },
|
||||||
Point.above(pt))
|
Point.above(pt))
|
||||||
@@ -510,10 +503,10 @@ local function fell()
|
|||||||
|
|
||||||
local pts = Util.shallowCopy(state.trees)
|
local pts = Util.shallowCopy(state.trees)
|
||||||
|
|
||||||
local pt = table.remove(pts, math.random(1, #pts))
|
local rpt = table.remove(pts, math.random(1, #pts))
|
||||||
|
|
||||||
-- give the pathfinder hints about what to avoid (state.trees)
|
-- give the pathfinder hints about what to avoid (state.trees)
|
||||||
if not turtle.faceAgainst(pt, { blocks = Util.shallowCopy(state.trees) }) or
|
if not turtle.faceAgainst(rpt, { blocks = Util.shallowCopy(state.trees) }) or
|
||||||
not string.match(inspect(turtle.inspect), 'minecraft:log') then
|
not string.match(inspect(turtle.inspect), 'minecraft:log') then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -523,7 +516,7 @@ local function fell()
|
|||||||
local fuel = turtle.getFuelLevel()
|
local fuel = turtle.getFuelLevel()
|
||||||
|
|
||||||
-- push this point to the start of this list
|
-- push this point to the start of this list
|
||||||
table.insert(pts, 1, pt)
|
table.insert(pts, 1, rpt)
|
||||||
|
|
||||||
Point.eachClosest(turtle.point, pts, function(pt)
|
Point.eachClosest(turtle.point, pts, function(pt)
|
||||||
if turtle.faceAgainst(pt, { blocks = Util.shallowCopy(state.trees) }) and
|
if turtle.faceAgainst(pt, { blocks = Util.shallowCopy(state.trees) }) and
|
||||||
@@ -545,7 +538,7 @@ local function moreTrees()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not state.chest_1 or turtle.getItemCount('minecraft:sapling') < 15 then
|
if not state.chest or turtle.getItemCount('minecraft:sapling') < 15 then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -570,7 +563,7 @@ local function moreTrees()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function getTurtleFacing(block)
|
local function getTurtleFacing(block)
|
||||||
local directions = {
|
local directions = {
|
||||||
[5] = 2,
|
[5] = 2,
|
||||||
[3] = 3,
|
[3] = 3,
|
||||||
@@ -586,7 +579,7 @@ function getTurtleFacing(block)
|
|||||||
return directions[bi.metadata]
|
return directions[bi.metadata]
|
||||||
end
|
end
|
||||||
|
|
||||||
function saveTurtleFacing()
|
local function saveTurtleFacing()
|
||||||
if not state.facing then
|
if not state.facing then
|
||||||
setState('facing', getTurtleFacing(CHEST))
|
setState('facing', getTurtleFacing(CHEST))
|
||||||
end
|
end
|
||||||
@@ -600,7 +593,7 @@ local function findGround()
|
|||||||
local s, block = turtle.inspectDown()
|
local s, block = turtle.inspectDown()
|
||||||
|
|
||||||
if not s then block = { name = 'minecraft:air', metadata = 0 } end
|
if not s then block = { name = 'minecraft:air', metadata = 0 } end
|
||||||
b = block.name .. ':' .. block.metadata
|
local b = block.name .. ':' .. block.metadata
|
||||||
|
|
||||||
if b == 'minecraft:dirt:0' or
|
if b == 'minecraft:dirt:0' or
|
||||||
b == 'minecraft:grass:0' or
|
b == 'minecraft:grass:0' or
|
||||||
@@ -633,10 +626,7 @@ local function findHome()
|
|||||||
end
|
end
|
||||||
|
|
||||||
print('Determining location')
|
print('Determining location')
|
||||||
|
turtle.point.heading = (getTurtleFacing(CHEST) - state.facing) % 4
|
||||||
turtle.point.heading = getTurtleFacing(CHEST)
|
|
||||||
turtle.setHeading(state.facing)
|
|
||||||
turtle.point.heading = 0
|
|
||||||
|
|
||||||
local pt = Point.copy(turtle.point)
|
local pt = Point.copy(turtle.point)
|
||||||
|
|
||||||
@@ -663,7 +653,7 @@ local function findHome()
|
|||||||
})
|
})
|
||||||
|
|
||||||
-- when pathfinding - don't leave this box
|
-- when pathfinding - don't leave this box
|
||||||
Pathing.setBox({
|
turtle.setPathingBox({
|
||||||
x = GRID.TL.x,
|
x = GRID.TL.x,
|
||||||
y = GRID.TL.y,
|
y = GRID.TL.y,
|
||||||
z = GRID.TL.z,
|
z = GRID.TL.z,
|
||||||
@@ -710,7 +700,7 @@ local tasks = {
|
|||||||
{ desc = 'Emptying furnace', fn = emptyFurnace },
|
{ desc = 'Emptying furnace', fn = emptyFurnace },
|
||||||
{ desc = 'Adding trees', fn = moreTrees },
|
{ desc = 'Adding trees', fn = moreTrees },
|
||||||
{ desc = 'Chopping', fn = fell },
|
{ desc = 'Chopping', fn = fell },
|
||||||
{ desc = 'Snacking', fn = eatSaplings },
|
-- { desc = 'Snacking', fn = eatSaplings },
|
||||||
{ desc = 'Creating chest', fn = createChests },
|
{ desc = 'Creating chest', fn = createChests },
|
||||||
{ desc = 'Creating furnace', fn = createFurnace },
|
{ desc = 'Creating furnace', fn = createFurnace },
|
||||||
{ desc = 'Making charcoal', fn = makeSingleCharcoal },
|
{ desc = 'Making charcoal', fn = makeSingleCharcoal },
|
||||||
@@ -725,13 +715,14 @@ local tasks = {
|
|||||||
|
|
||||||
local s, m = turtle.run(function()
|
local s, m = turtle.run(function()
|
||||||
|
|
||||||
|
turtle.addFeatures('level', 'crafting')
|
||||||
turtle.setPolicy("attack")
|
turtle.setPolicy("attack")
|
||||||
|
|
||||||
while not turtle.abort do
|
while not turtle.isAborted() do
|
||||||
print('fuel: ' .. turtle.getFuelLevel())
|
print('fuel: ' .. turtle.getFuelLevel())
|
||||||
for _,task in ipairs(Util.shallowCopy(tasks)) do
|
for _,task in ipairs(Util.shallowCopy(tasks)) do
|
||||||
--print(task.desc)
|
--print(task.desc)
|
||||||
turtle.status = task.desc
|
turtle.setStatus(task.desc)
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
if not task.fn() then
|
if not task.fn() then
|
||||||
Util.filterInplace(tasks, function(v) return v.fn ~= task.fn end)
|
Util.filterInplace(tasks, function(v) return v.fn ~= task.fn end)
|
||||||
@@ -741,5 +732,5 @@ local s, m = turtle.run(function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
if not s then
|
if not s then
|
||||||
error('Failed')
|
error(m or 'Failed')
|
||||||
end
|
end
|
||||||
|
|||||||
1
etc/fstab.ignore
Normal file
1
etc/fstab.ignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
forced fstab overwrite
|
||||||
87
etc/recipes/appliedenergistics2.db
Normal file
87
etc/recipes/appliedenergistics2.db
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
[ "appliedenergistics2:quartz_glass:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"appliedenergistics2:material:2",
|
||||||
|
"minecraft:glass:0",
|
||||||
|
"appliedenergistics2:material:2",
|
||||||
|
[ 9 ] = "appliedenergistics2:material:2",
|
||||||
|
[ 10 ] = "minecraft:glass:0",
|
||||||
|
[ 11 ] = "appliedenergistics2:material:2",
|
||||||
|
[ 5 ] = "minecraft:glass:0",
|
||||||
|
[ 6 ] = "appliedenergistics2:material:2",
|
||||||
|
[ 7 ] = "minecraft:glass:0",
|
||||||
|
},
|
||||||
|
count = 4,
|
||||||
|
},
|
||||||
|
[ "appliedenergistics2:material:43" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"appliedenergistics2:material:0",
|
||||||
|
"appliedenergistics2:material:8",
|
||||||
|
"appliedenergistics2:material:22",
|
||||||
|
},
|
||||||
|
count = 2,
|
||||||
|
},
|
||||||
|
[ "appliedenergistics2:material:44" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 5 ] = "minecraft:quartz:0",
|
||||||
|
[ 6 ] = "appliedenergistics2:material:8",
|
||||||
|
[ 7 ] = "appliedenergistics2:material:22",
|
||||||
|
},
|
||||||
|
count = 2,
|
||||||
|
},
|
||||||
|
[ "appliedenergistics2:material:35" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
"appliedenergistics2:material:0",
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
[ 5 ] = "appliedenergistics2:material:0",
|
||||||
|
[ 6 ] = "appliedenergistics2:material:22",
|
||||||
|
[ 7 ] = "appliedenergistics2:material:0",
|
||||||
|
[ 9 ] = "minecraft:redstone:0",
|
||||||
|
[ 10 ] = "appliedenergistics2:material:0",
|
||||||
|
[ 11 ] = "minecraft:redstone:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "appliedenergistics2:interface:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:glass:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:glass:0",
|
||||||
|
[ 11 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 5 ] = "appliedenergistics2:material:44",
|
||||||
|
[ 7 ] = "appliedenergistics2:material:43",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "appliedenergistics2:material:36" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
"appliedenergistics2:material:23",
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
[ 5 ] = "appliedenergistics2:material:35",
|
||||||
|
[ 6 ] = "appliedenergistics2:quartz_glass:0",
|
||||||
|
[ 7 ] = "appliedenergistics2:material:35",
|
||||||
|
[ 9 ] = "minecraft:redstone:0",
|
||||||
|
[ 10 ] = "appliedenergistics2:material:35",
|
||||||
|
[ 11 ] = "minecraft:redstone:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "appliedenergistics2:material:37" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:glowstone_dust:0",
|
||||||
|
"appliedenergistics2:material:24",
|
||||||
|
"minecraft:glowstone_dust:0",
|
||||||
|
[ 5 ] = "appliedenergistics2:material:36",
|
||||||
|
[ 6 ] = "appliedenergistics2:quartz_glass:0",
|
||||||
|
[ 7 ] = "appliedenergistics2:material:36",
|
||||||
|
[ 9 ] = "minecraft:glowstone_dust:0",
|
||||||
|
[ 10 ] = "appliedenergistics2:material:36",
|
||||||
|
[ 11 ] = "minecraft:glowstone_dust:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
87
etc/recipes/computercraft.db
Normal file
87
etc/recipes/computercraft.db
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
[ "computercraft:turtle_advanced:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:chest:0",
|
||||||
|
[ 11 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 6 ] = "computercraft:computer:16384",
|
||||||
|
[ 7 ] = "minecraft:gold_ingot:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "computercraft:pocket_computer:1" ] = {
|
||||||
|
count = 1,
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:glass_pane:0",
|
||||||
|
[ 11 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 6 ] = "minecraft:golden_apple:0",
|
||||||
|
[ 7 ] = "minecraft:gold_ingot:0",
|
||||||
|
},
|
||||||
|
maxCount = 1,
|
||||||
|
},
|
||||||
|
[ "computercraft:peripheral:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:stone:0",
|
||||||
|
"minecraft:stone:0",
|
||||||
|
"minecraft:stone:0",
|
||||||
|
[ 9 ] = "minecraft:stone:0",
|
||||||
|
[ 10 ] = "minecraft:redstone:0",
|
||||||
|
[ 11 ] = "minecraft:stone:0",
|
||||||
|
[ 5 ] = "minecraft:stone:0",
|
||||||
|
[ 6 ] = "minecraft:redstone:0",
|
||||||
|
[ 7 ] = "minecraft:stone:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "computercraft:peripheral:4" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 11 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 6 ] = "minecraft:glass_pane:0",
|
||||||
|
[ 7 ] = "minecraft:gold_ingot:0",
|
||||||
|
},
|
||||||
|
count = 4,
|
||||||
|
},
|
||||||
|
[ "computercraft:advanced_modem:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 11 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 6 ] = "minecraft:ender_eye:0",
|
||||||
|
[ 7 ] = "minecraft:gold_ingot:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "computercraft:computer:16384" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:glass_pane:0",
|
||||||
|
[ 11 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 6 ] = "minecraft:redstone:0",
|
||||||
|
[ 7 ] = "minecraft:gold_ingot:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
544
etc/recipes/enderio.db
Normal file
544
etc/recipes/enderio.db
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
{
|
||||||
|
[ "enderio:blockAlloySmelter:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:furnace:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:cauldron:0",
|
||||||
|
[ 11 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:furnace:0",
|
||||||
|
[ 6 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 7 ] = "minecraft:furnace:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockBuffer:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 10 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 11 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 6 ] = "minecraft:chest:0",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockCapBank:3" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
"enderio:itemBasicCapacitor:2",
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 10 ] = "enderio:itemBasicCapacitor:2",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 5 ] = "enderio:itemBasicCapacitor:2",
|
||||||
|
[ 6 ] = "enderio:itemMaterial:6",
|
||||||
|
[ 7 ] = "enderio:itemBasicCapacitor:2",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockExperienceObelisk:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 9 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 10 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 2 ] = "enderio:itemXpTransfer:0",
|
||||||
|
[ 6 ] = "enderio:itemAlloy:7",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockFarmStation:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
"minecraft:diamond_hoe:*",
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:5",
|
||||||
|
[ 10 ] = "enderio:itemFrankenSkull:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:5",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 6 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockKillerJoe:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:6",
|
||||||
|
"enderio:itemAlloy:6",
|
||||||
|
"enderio:itemAlloy:6",
|
||||||
|
[ 9 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 10 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 11 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 5 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 6 ] = "enderio:itemFrankenSkull:2",
|
||||||
|
[ 7 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockPainter:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:quartz:0",
|
||||||
|
"minecraft:diamond:0",
|
||||||
|
"minecraft:quartz:0",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 10 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 6 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockReservoir:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:blockFusedQuartz:0",
|
||||||
|
"enderio:blockFusedQuartz:0",
|
||||||
|
"enderio:blockFusedQuartz:0",
|
||||||
|
[ 9 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 10 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 11 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 5 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 6 ] = "minecraft:cauldron:0",
|
||||||
|
[ 7 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
},
|
||||||
|
count = 4,
|
||||||
|
},
|
||||||
|
[ "enderio:blockSagMill:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:flint:0",
|
||||||
|
"minecraft:flint:0",
|
||||||
|
"minecraft:flint:0",
|
||||||
|
[ 9 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:piston:0",
|
||||||
|
[ 11 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 6 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 7 ] = "minecraft:iron_ingot:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockSliceAndSplice:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:7",
|
||||||
|
"minecraft:skull:0",
|
||||||
|
"enderio:itemAlloy:7",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 10 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 5 ] = "minecraft:iron_axe:*",
|
||||||
|
[ 6 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 7 ] = "minecraft:shears:*",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockSolarPanel:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:1",
|
||||||
|
"enderio:blockFusedQuartz:0",
|
||||||
|
"enderio:itemAlloy:1",
|
||||||
|
[ 9 ] = "enderio:itemBasicCapacitor:0",
|
||||||
|
[ 10 ] = "minecraft:daylight_detector:0",
|
||||||
|
[ 11 ] = "enderio:itemBasicCapacitor:0",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:2",
|
||||||
|
[ 6 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:2",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockSolarPanel:1" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:5",
|
||||||
|
"enderio:blockFusedQuartz:2",
|
||||||
|
"enderio:itemAlloy:5",
|
||||||
|
[ 9 ] = "enderio:itemBasicCapacitor:1",
|
||||||
|
[ 10 ] = "minecraft:daylight_detector:0",
|
||||||
|
[ 11 ] = "enderio:itemBasicCapacitor:1",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:2",
|
||||||
|
[ 6 ] = "enderio:blockFusedQuartz:2",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:2",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockSolarPanel:2" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:7",
|
||||||
|
"enderio:blockFusedQuartz:4",
|
||||||
|
"enderio:itemAlloy:7",
|
||||||
|
[ 9 ] = "enderio:blockSolarPanel:1",
|
||||||
|
[ 10 ] = "enderio:blockSolarPanel:1",
|
||||||
|
[ 11 ] = "enderio:blockSolarPanel:1",
|
||||||
|
[ 5 ] = "enderio:itemBasicCapacitor:2",
|
||||||
|
[ 6 ] = "enderio:itemMaterial:8",
|
||||||
|
[ 7 ] = "enderio:itemBasicCapacitor:2",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockSoulBinder:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:7",
|
||||||
|
"enderio:blockEndermanSkull:0",
|
||||||
|
"enderio:itemAlloy:7",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 10 ] = "minecraft:skull:0",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 5 ] = "minecraft:skull:4",
|
||||||
|
[ 6 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 7 ] = "minecraft:skull:2",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockTank:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:iron_bars:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 10 ] = "minecraft:iron_bars:0",
|
||||||
|
[ 11 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:iron_bars:0",
|
||||||
|
[ 6 ] = "minecraft:glass:0",
|
||||||
|
[ 7 ] = "minecraft:iron_bars:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockTransceiver:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
"enderio:itemFrankenSkull:3",
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 10 ] = "enderio:itemBasicCapacitor:2",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 5 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 6 ] = "enderio:itemMaterial:8",
|
||||||
|
[ 7 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockVacuumChest:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
[ 9 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:5",
|
||||||
|
[ 11 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 5 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 6 ] = "minecraft:chest:0",
|
||||||
|
[ 7 ] = "minecraft:iron_ingot:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockVat:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
"minecraft:cauldron:0",
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 10 ] = "minecraft:furnace:0",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 5 ] = "enderio:blockTank:0",
|
||||||
|
[ 6 ] = "enderio:itemMachinePart:0",
|
||||||
|
[ 7 ] = "enderio:blockTank:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:blockWirelessCharger:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
"enderio:itemAlloy:0",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 10 ] = "enderio:itemBasicCapacitor:2",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 6 ] = "enderio:itemFrankenSkull:3",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemBasicCapacitor:2" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "enderio:itemAlloy:2",
|
||||||
|
[ 2 ] = "enderio:itemAlloy:2",
|
||||||
|
[ 5 ] = "enderio:itemBasicCapacitor:1",
|
||||||
|
[ 6 ] = "minecraft:glowstone:0",
|
||||||
|
[ 7 ] = "enderio:itemBasicCapacitor:1",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemBasicFilterUpgrade:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "minecraft:paper:0",
|
||||||
|
[ 2 ] = "minecraft:paper:0",
|
||||||
|
[ 5 ] = "minecraft:paper:0",
|
||||||
|
[ 6 ] = "minecraft:hopper:0",
|
||||||
|
[ 7 ] = "minecraft:paper:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemBasicFilterUpgrade:1" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
"minecraft:paper:0",
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
[ 9 ] = "minecraft:redstone:0",
|
||||||
|
[ 10 ] = "minecraft:paper:0",
|
||||||
|
[ 11 ] = "minecraft:redstone:0",
|
||||||
|
[ 5 ] = "minecraft:paper:0",
|
||||||
|
[ 6 ] = "enderio:itemFrankenSkull:1",
|
||||||
|
[ 7 ] = "minecraft:paper:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemBasicFilterUpgrade:2" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:comparator:0",
|
||||||
|
"enderio:itemBasicFilterUpgrade:1",
|
||||||
|
"minecraft:comparator:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemConduitFacade:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 7 ] = "enderio:itemMaterial:1",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemExtractSpeedUpgrade:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 10 ] = "minecraft:redstone_torch:0",
|
||||||
|
[ 11 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:0",
|
||||||
|
[ 6 ] = "minecraft:piston:0",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemItemConduit:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:itemMaterial:3",
|
||||||
|
[ 6 ] = "enderio:itemMaterial:3",
|
||||||
|
[ 7 ] = "enderio:itemMaterial:3",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemLiquidConduit:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:blockFusedQuartz:1",
|
||||||
|
[ 6 ] = "enderio:blockFusedQuartz:1",
|
||||||
|
[ 7 ] = "enderio:blockFusedQuartz:1",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemLiquidConduit:1" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 6 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 7 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemLiquidConduit:2" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:2",
|
||||||
|
[ 6 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:2",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemMachinePart:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:iron_bars:0",
|
||||||
|
"minecraft:iron_ingot:0",
|
||||||
|
"minecraft:iron_bars:0",
|
||||||
|
[ 9 ] = "minecraft:iron_bars:0",
|
||||||
|
[ 10 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 11 ] = "minecraft:iron_bars:0",
|
||||||
|
[ 5 ] = "minecraft:iron_ingot:0",
|
||||||
|
[ 6 ] = "enderio:itemBasicCapacitor:0",
|
||||||
|
[ 7 ] = "minecraft:iron_ingot:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemMachinePart:1" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:stick:0",
|
||||||
|
"minecraft:cobblestone:0",
|
||||||
|
"minecraft:stick:0",
|
||||||
|
[ 9 ] = "minecraft:stick:0",
|
||||||
|
[ 10 ] = "minecraft:cobblestone:0",
|
||||||
|
[ 11 ] = "minecraft:stick:0",
|
||||||
|
[ 5 ] = "minecraft:cobblestone:0",
|
||||||
|
[ 7 ] = "minecraft:cobblestone:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemMaterial:2" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:gravel:0",
|
||||||
|
"minecraft:clay_ball:0",
|
||||||
|
"minecraft:gravel:0",
|
||||||
|
[ 9 ] = "minecraft:gravel:0",
|
||||||
|
[ 10 ] = "minecraft:clay_ball:0",
|
||||||
|
[ 11 ] = "minecraft:gravel:0",
|
||||||
|
[ 5 ] = "minecraft:sand:0",
|
||||||
|
[ 6 ] = "minecraft:gravel:0",
|
||||||
|
[ 7 ] = "minecraft:sand:0",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemMaterial:3" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:5",
|
||||||
|
},
|
||||||
|
count = 9,
|
||||||
|
},
|
||||||
|
[ "enderio:itemMaterial:4" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemAlloy:2",
|
||||||
|
},
|
||||||
|
count = 9,
|
||||||
|
},
|
||||||
|
[ "enderio:itemMaterial:5" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:3",
|
||||||
|
"enderio:itemMaterial:3",
|
||||||
|
"enderio:itemMaterial:3",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:3",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:3",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:3",
|
||||||
|
[ 5 ] = "enderio:itemMaterial:3",
|
||||||
|
[ 6 ] = "minecraft:diamond:0",
|
||||||
|
[ 7 ] = "enderio:itemMaterial:3",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemMaterial:6" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:4",
|
||||||
|
"enderio:itemMaterial:4",
|
||||||
|
"enderio:itemMaterial:4",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:4",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:4",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:4",
|
||||||
|
[ 5 ] = "enderio:itemMaterial:4",
|
||||||
|
[ 6 ] = "minecraft:emerald:0",
|
||||||
|
[ 7 ] = "enderio:itemMaterial:4",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemPowerConduit:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:4",
|
||||||
|
[ 6 ] = "enderio:itemAlloy:4",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:4",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemPowerConduit:1" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:1",
|
||||||
|
[ 6 ] = "enderio:itemPowerConduit:0",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:1",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemPowerConduit:2" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:2",
|
||||||
|
[ 6 ] = "enderio:itemAlloy:2",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:2",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemRedstoneConduit:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
"enderio:itemMaterial:1",
|
||||||
|
[ 9 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 10 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 11 ] = "enderio:itemMaterial:1",
|
||||||
|
[ 5 ] = "enderio:itemAlloy:3",
|
||||||
|
[ 6 ] = "enderio:itemAlloy:3",
|
||||||
|
[ 7 ] = "enderio:itemAlloy:3",
|
||||||
|
},
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
[ "enderio:itemSoulVessel:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 7 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 2 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 10 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
[ 5 ] = "enderio:blockFusedQuartz:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "enderio:itemXpTransfer:0" ] = {
|
||||||
|
count = 1,
|
||||||
|
ingredients = {
|
||||||
|
[ 6 ] = "enderio:itemAlloy:1",
|
||||||
|
[ 3 ] = "enderio:itemAlloy:7",
|
||||||
|
[ 9 ] = "enderio:itemAlloy:7",
|
||||||
|
},
|
||||||
|
maxCount = 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
12
etc/recipes/exnihilo.db
Normal file
12
etc/recipes/exnihilo.db
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
[ "exnihiloadscensio:hammerStone:0" ] = {
|
||||||
|
maxCount = 1,
|
||||||
|
ingredients = {
|
||||||
|
[ 7 ] = "minecraft:cobblestone:0",
|
||||||
|
[ 9 ] = "minecraft:stick:0",
|
||||||
|
[ 2 ] = "minecraft:cobblestone:0",
|
||||||
|
[ 6 ] = "minecraft:stick:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
21
etc/recipes/extrautils2.db
Normal file
21
etc/recipes/extrautils2.db
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
[ "extrautils2:user:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:dropper:0",
|
||||||
|
"extrautils2:ingredients:0",
|
||||||
|
[ 5 ] = "minecraft:lever:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "extrautils2:endershard:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:ender_pearl:0",
|
||||||
|
"extrautils2:glasscutter:*",
|
||||||
|
},
|
||||||
|
craftingTools = {
|
||||||
|
[ "extrautils2:glasscutter:*" ] = true,
|
||||||
|
},
|
||||||
|
maxCount = 1,
|
||||||
|
count = 8,
|
||||||
|
},
|
||||||
|
}
|
||||||
58
etc/recipes/mekanism.db
Normal file
58
etc/recipes/mekanism.db
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
[ "mekanism:EnergyTablet:0:3a153e5a66ba42a2d96ffd50ba64918b" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"minecraft:redstone:0",
|
||||||
|
[ 9 ] = "minecraft:redstone:0",
|
||||||
|
[ 10 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 11 ] = "minecraft:redstone:0",
|
||||||
|
[ 5 ] = "mekanism:EnrichedAlloy:0",
|
||||||
|
[ 6 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 7 ] = "mekanism:EnrichedAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mekanism:SpeedUpgrade:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "minecraft:glass:0",
|
||||||
|
[ 2 ] = "minecraft:glass:0",
|
||||||
|
[ 5 ] = "mekanism:EnrichedAlloy:0",
|
||||||
|
[ 6 ] = "mekanism:Dust:2",
|
||||||
|
[ 7 ] = "mekanism:EnrichedAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mekanism:ControlCircuit:1" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"mekanism:EnrichedAlloy:0",
|
||||||
|
"mekanism:ControlCircuit:0",
|
||||||
|
"mekanism:EnrichedAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mekanism:BasicBlock:8" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"bigreactors:ingotmetals:5",
|
||||||
|
"minecraft:glass:0",
|
||||||
|
"bigreactors:ingotmetals:5",
|
||||||
|
[ 9 ] = "bigreactors:ingotmetals:5",
|
||||||
|
[ 10 ] = "minecraft:glass:0",
|
||||||
|
[ 11 ] = "bigreactors:ingotmetals:5",
|
||||||
|
[ 5 ] = "minecraft:glass:0",
|
||||||
|
[ 6 ] = "mekanism:Ingot:1",
|
||||||
|
[ 7 ] = "minecraft:glass:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mekanism:EnergyUpgrade:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "minecraft:glass:0",
|
||||||
|
[ 2 ] = "minecraft:glass:0",
|
||||||
|
[ 5 ] = "mekanism:EnrichedAlloy:0",
|
||||||
|
[ 6 ] = "exnihiloadscensio:itemOreGold:2",
|
||||||
|
[ 7 ] = "mekanism:EnrichedAlloy:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
178
etc/recipes/mysticalagriculture.db
Normal file
178
etc/recipes/mysticalagriculture.db
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
{
|
||||||
|
[ "mysticalagriculture:supremium_ingot:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "mysticalagriculture:supremium_essence:0",
|
||||||
|
[ 2 ] = "mysticalagriculture:supremium_essence:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:supremium_essence:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:superium_ingot:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:supremium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:prudentium_ingot:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 2 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:inferium_ingot:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:intermedium_ingot:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 2 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:prudentium_ingot:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:superium_armor_core:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:superium_essence:0",
|
||||||
|
"minecraft:diamond_block:0",
|
||||||
|
"mysticalagriculture:superium_essence:0",
|
||||||
|
[ 5 ] = "minecraft:emerald:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:intermedium_armor_core:0",
|
||||||
|
[ 7 ] = "minecraft:emerald:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:superium_essence:0",
|
||||||
|
[ 10 ] = "minecraft:emerald:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:superium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:inferium_ingot:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 2 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:base_essence_ingot:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:intermedium_armor_core:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:intermedium_essence:0",
|
||||||
|
"minecraft:gold_block:0",
|
||||||
|
"mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 5 ] = "minecraft:diamond:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:prudentium_armor_core:0",
|
||||||
|
[ 7 ] = "minecraft:diamond:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 10 ] = "minecraft:diamond:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:infusion_crystal:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:prosperity_shard:0",
|
||||||
|
"mysticalagriculture:inferium_essence:0",
|
||||||
|
"mysticalagriculture:prosperity_shard:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:prosperity_shard:0",
|
||||||
|
[ 10 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:prosperity_shard:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 6 ] = "minecraft:diamond:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:supremium_armor_core:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:supremium_essence:0",
|
||||||
|
"minecraft:nether_star:0",
|
||||||
|
"mysticalagriculture:supremium_essence:0",
|
||||||
|
[ 5 ] = "minecraft:skull:1",
|
||||||
|
[ 6 ] = "mysticalagriculture:superium_armor_core:0",
|
||||||
|
[ 7 ] = "minecraft:skull:1",
|
||||||
|
[ 9 ] = "mysticalagriculture:supremium_essence:0",
|
||||||
|
[ 10 ] = "minecraft:skull:1",
|
||||||
|
[ 11 ] = "mysticalagriculture:supremium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:inferium_armor_core:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:inferium_essence:0",
|
||||||
|
"minecraft:gold_ingot:0",
|
||||||
|
"mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 5 ] = "minecraft:leather:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:base_essence_ingot:0",
|
||||||
|
[ 7 ] = "minecraft:leather:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 10 ] = "minecraft:leather:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:base_essence_ingot:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
[ 10 ] = "mysticalagriculture:prosperity_shard:0",
|
||||||
|
[ 2 ] = "mysticalagriculture:prosperity_shard:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:prosperity_shard:0",
|
||||||
|
[ 6 ] = "thermalfoundation:material:136",
|
||||||
|
[ 7 ] = "mysticalagriculture:prosperity_shard:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:tier2_inferium_seeds:0" ] = {
|
||||||
|
count = 1,
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:prudentium_essence:0",
|
||||||
|
"mysticalagriculture:prudentium_essence:0",
|
||||||
|
"mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 10 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:tier1_inferium_seeds:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:tier3_inferium_seeds:0" ] = {
|
||||||
|
count = 1,
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:intermedium_essence:0",
|
||||||
|
"mysticalagriculture:intermedium_essence:0",
|
||||||
|
"mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 10 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:tier2_inferium_seeds:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:intermedium_essence:0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:tier1_inferium_seeds:0" ] = {
|
||||||
|
count = 1,
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:inferium_essence:0",
|
||||||
|
"mysticalagriculture:inferium_essence:0",
|
||||||
|
"mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 10 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 5 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
[ 6 ] = "minecraft:wheat_seeds:0",
|
||||||
|
[ 7 ] = "mysticalagriculture:inferium_essence:0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[ "mysticalagriculture:prudentium_armor_core:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"mysticalagriculture:prudentium_essence:0",
|
||||||
|
"minecraft:lapis_block:0",
|
||||||
|
"mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 5 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 6 ] = "mysticalagriculture:inferium_armor_core:0",
|
||||||
|
[ 7 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 9 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
[ 10 ] = "minecraft:gold_ingot:0",
|
||||||
|
[ 11 ] = "mysticalagriculture:prudentium_essence:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
28
etc/recipes/storagedrawers.db
Normal file
28
etc/recipes/storagedrawers.db
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
[ "storagedrawers:basicDrawers:0:b85f006d9f6aa0e06184f8931d4e85c1" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:planks:0",
|
||||||
|
"minecraft:planks:0",
|
||||||
|
"minecraft:planks:0",
|
||||||
|
[ 9 ] = "minecraft:planks:0",
|
||||||
|
[ 10 ] = "minecraft:planks:0",
|
||||||
|
[ 11 ] = "minecraft:planks:0",
|
||||||
|
[ 6 ] = "minecraft:chest:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "storagedrawers:upgradeTemplate:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:stick:0",
|
||||||
|
"minecraft:stick:0",
|
||||||
|
"minecraft:stick:0",
|
||||||
|
[ 9 ] = "minecraft:stick:0",
|
||||||
|
[ 10 ] = "minecraft:stick:0",
|
||||||
|
[ 11 ] = "minecraft:stick:0",
|
||||||
|
[ 5 ] = "minecraft:stick:0",
|
||||||
|
[ 6 ] = "storagedrawers:basicDrawers:0:b85f006d9f6aa0e06184f8931d4e85c1",
|
||||||
|
[ 7 ] = "minecraft:stick:0",
|
||||||
|
},
|
||||||
|
count = 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
22
etc/recipes/tconstruct.db
Normal file
22
etc/recipes/tconstruct.db
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
[ "minecraft:book:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:paper:0",
|
||||||
|
"minecraft:paper:0",
|
||||||
|
"minecraft:paper:0",
|
||||||
|
[ 5 ] = "minecraft:string:0",
|
||||||
|
[ 6 ] = "tconstruct:pattern:0",
|
||||||
|
[ 7 ] = "tconstruct:pattern:0",
|
||||||
|
},
|
||||||
|
count = 1,
|
||||||
|
},
|
||||||
|
[ "tconstruct:pattern:0" ] = {
|
||||||
|
ingredients = {
|
||||||
|
"minecraft:planks:0",
|
||||||
|
"minecraft:stick:0",
|
||||||
|
[ 5 ] = "minecraft:stick:0",
|
||||||
|
[ 6 ] = "minecraft:planks:0",
|
||||||
|
},
|
||||||
|
count = 4,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
turtle.abortAction()
|
turtle.abort(true)
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
|
local os = _G.os
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
local function follow(id)
|
local function follow(id)
|
||||||
|
|
||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local Point = require('point')
|
local Point = require('point')
|
||||||
local Socket = require('socket')
|
local Socket = require('socket')
|
||||||
|
|
||||||
turtle.status = 'follow ' .. id
|
turtle.setStatus('follow ' .. id)
|
||||||
|
|
||||||
if not turtle.enableGPS() then
|
if not turtle.enableGPS() then
|
||||||
error('turtle: No GPS found')
|
error('turtle: No GPS found')
|
||||||
@@ -55,7 +58,7 @@ local function follow(id)
|
|||||||
Event.onInterval(.5, function()
|
Event.onInterval(.5, function()
|
||||||
|
|
||||||
local function getRemotePoint()
|
local function getRemotePoint()
|
||||||
if not turtle.abort then
|
if not turtle.isAborted() then
|
||||||
if socket:write({ type = 'gps' }) then
|
if socket:write({ type = 'gps' }) then
|
||||||
return socket:read(3)
|
return socket:read(3)
|
||||||
end
|
end
|
||||||
@@ -65,7 +68,7 @@ local function follow(id)
|
|||||||
-- sometimes gps will fail if moving
|
-- sometimes gps will fail if moving
|
||||||
local pt, d
|
local pt, d
|
||||||
|
|
||||||
for i = 1, 3 do
|
for _ = 1, 3 do
|
||||||
pt, d = getRemotePoint()
|
pt, d = getRemotePoint()
|
||||||
if pt then
|
if pt then
|
||||||
break
|
break
|
||||||
@@ -73,22 +76,22 @@ local function follow(id)
|
|||||||
os.sleep(.5)
|
os.sleep(.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not pt or turtle.abort then
|
if not pt or turtle.isAborted() then
|
||||||
error('Did not receive GPS location')
|
error('Did not receive GPS location')
|
||||||
end
|
end
|
||||||
|
|
||||||
if not lastPoint or (lastPoint.x ~= pt.x or lastPoint.y ~= pt.y or lastPoint.z ~= pt.z) then
|
if not lastPoint or (lastPoint.x ~= pt.x or lastPoint.y ~= pt.y or lastPoint.z ~= pt.z) then
|
||||||
|
|
||||||
if following then
|
if following then
|
||||||
turtle.abort = true
|
turtle.getState().abort = true
|
||||||
while following do
|
while following do
|
||||||
os.sleep(.1)
|
os.sleep(.1)
|
||||||
end
|
end
|
||||||
turtle.abort = false
|
turtle.getState().abort = false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check if gps is inaccurate (player moving too fast)
|
-- check if gps is inaccurate (player moving too fast)
|
||||||
if d < Point.pythagoreanDistance(turtle.point, pt) + 10 then
|
if d < Point.distance(turtle.point, pt) + 10 then
|
||||||
lastPoint = Point.copy(pt)
|
lastPoint = Point.copy(pt)
|
||||||
following = true
|
following = true
|
||||||
os.queueEvent('turtle_follow', pt)
|
os.queueEvent('turtle_follow', pt)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
turtle.run(turtle.gotoGPSHome)
|
local Home = require('turtle.home')
|
||||||
|
turtle.run(Home.go)
|
||||||
|
|||||||
@@ -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,8 +1,11 @@
|
|||||||
requireInjector(getfenv(1))
|
_G.requireInjector()
|
||||||
|
|
||||||
local Point = require('point')
|
local Point = require('point')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local os = _G.os
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
local checkedNodes, nodes
|
local checkedNodes, nodes
|
||||||
|
|
||||||
local function addNode(node)
|
local function addNode(node)
|
||||||
@@ -47,7 +50,7 @@ local function findObsidian()
|
|||||||
if turtle.getItemCount(16) > 0 then
|
if turtle.getItemCount(16) > 0 then
|
||||||
print('Inventory full')
|
print('Inventory full')
|
||||||
print('Enter to continue...')
|
print('Enter to continue...')
|
||||||
read()
|
_G.read()
|
||||||
end
|
end
|
||||||
|
|
||||||
if b and b.name == 'minecraft:obsidian' then
|
if b and b.name == 'minecraft:obsidian' then
|
||||||
@@ -63,40 +66,43 @@ local function findObsidian()
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
local node = Point.closest(turtle.point, nodes)
|
node = Point.closest(turtle.point, nodes)
|
||||||
if not turtle.gotoPoint(node) then
|
if not turtle._goto(node) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
until turtle.abort
|
until turtle.isAborted()
|
||||||
end
|
end
|
||||||
|
|
||||||
turtle.reset()
|
turtle.run(function()
|
||||||
turtle.setPolicy(turtle.policies.digOnly)
|
turtle.reset()
|
||||||
local s, m = turtle.run(function()
|
turtle.setPolicy(turtle.policies.digOnly)
|
||||||
repeat
|
|
||||||
|
|
||||||
checkedNodes = { }
|
local s, m = pcall(function()
|
||||||
nodes = { }
|
repeat
|
||||||
|
checkedNodes = { }
|
||||||
|
nodes = { }
|
||||||
|
|
||||||
local _,b = turtle.inspectDown()
|
local _,b = turtle.inspectDown()
|
||||||
if not b or b.name ~= 'minecraft:obsidian' then
|
if not b or b.name ~= 'minecraft:obsidian' then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
findObsidian()
|
findObsidian()
|
||||||
if not turtle.select('minecraft:water_bucket') then
|
if not turtle.select('minecraft:water_bucket') then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
turtle.goto(0, 0)
|
turtle._goto({ x = 0, z = 0 })
|
||||||
turtle.placeDown()
|
turtle.placeDown()
|
||||||
os.sleep(2)
|
os.sleep(2)
|
||||||
turtle.placeDown()
|
turtle.placeDown()
|
||||||
turtle.down()
|
turtle.down()
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
until turtle.abort
|
until turtle.isAborted()
|
||||||
|
end)
|
||||||
|
|
||||||
|
if not s and m then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
|
|
||||||
|
turtle._goto({ x = 0, y = 0, z = 0, heading = 0 })
|
||||||
end)
|
end)
|
||||||
turtle.goto(0, 0, 0, 0)
|
|
||||||
turtle.reset()
|
|
||||||
if not s and m then
|
|
||||||
error(m)
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
turtle.run(turtle.setGPSHome)
|
local Home = require('turtle.home')
|
||||||
|
turtle.run(Home.set)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ local function summon(id)
|
|||||||
local Point = require('point')
|
local Point = require('point')
|
||||||
local Socket = require('socket')
|
local Socket = require('socket')
|
||||||
|
|
||||||
turtle.status = 'GPSing'
|
turtle.setStatus('GPSing')
|
||||||
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 })
|
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 })
|
||||||
|
|
||||||
local pts = {
|
local pts = {
|
||||||
@@ -32,7 +32,7 @@ local function summon(id)
|
|||||||
local function doGPS()
|
local function doGPS()
|
||||||
tFixes = { }
|
tFixes = { }
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
if not turtle.gotoPoint(pts[i]) then
|
if not turtle._goto(pts[i]) then
|
||||||
error('turtle: Unable to perform GPS maneuver')
|
error('turtle: Unable to perform GPS maneuver')
|
||||||
end
|
end
|
||||||
local distance = getDistance()
|
local distance = getDistance()
|
||||||
@@ -64,7 +64,7 @@ local function summon(id)
|
|||||||
local pt = { x = pos.x, y = pos.y, z = pos.z }
|
local pt = { x = pos.x, y = pos.y, z = pos.z }
|
||||||
local _, h = Point.calculateMoves(turtle.getPoint(), pt)
|
local _, h = Point.calculateMoves(turtle.getPoint(), pt)
|
||||||
local hi = turtle.getHeadingInfo(h)
|
local hi = turtle.getHeadingInfo(h)
|
||||||
turtle.status = 'recalling'
|
turtle.setStatus('recalling')
|
||||||
turtle.pathfind({ x = pt.x - hi.xd, z = pt.z - hi.zd, y = pt.y - hi.yd, heading = h })
|
turtle.pathfind({ x = pt.x - hi.xd, z = pt.z - hi.zd, y = pt.y - hi.yd, heading = h })
|
||||||
else
|
else
|
||||||
error("turtle: Could not determine position")
|
error("turtle: Could not determine position")
|
||||||
|
|||||||
Reference in New Issue
Block a user